When an Expired Memory Blocks the New One: mem0 OSS Expiry, Deduplication and the Write That Never Lands
Your agent stored user prefers aisle seats with an expiration date. The date passed. The user says it again. You call add() with a fresh expiration_date, get no exception, get an empty results list, and get_all() shows nothing. The fact never lands, and it will never land as long as the expired copy is what the search returns. On mem0ai 2.2.1 — the Python OSS package, self-hosted — the cause is a read/write asymmetry. Expiration is applied as a filter on the read paths but not on the ADD path. The expired row is still handed to the extraction LLM as an “existing memory”, and its hash is still loaded into the dedup set, so the fresh write is dropped as a duplicate of a record the user can no longer see. The same write machinery adds a second dependency: an update that only touches metadata or the expiry date still calls the embedding provider, and a provider error stops that update before anything is persisted. ...