{"record":{"id":"6c40a3abcab3c210","repo":"bytedance/deer-flow","slug":"failed-to-save-cleared-memory-data","errorCode":null,"errorMessage":"Failed to save cleared memory data","messagePattern":"Failed to save cleared memory data","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py","lineNumber":884,"sourceCode":"                        {\n                            \"deletes\": [str(fact.get(\"id\")) for fact in facts],\n                            \"deleteRevisions\": {str(fact.get(\"id\")): int(fact.get(\"revision\") or 1) for fact in facts},\n                        },\n                        agent_name=agent_name,\n                        user_id=user_id,\n                        expected_manifest_revision=int(current.get(\"revision\") or 0),\n                    )\n                    return self.reload_memory_data(agent_name, user_id=user_id)\n                except MemoryManifestRevisionConflict:\n                    if attempt == 2:\n                        raise\n                    logger.info(\"Retrying scoped memory clear from a fresh snapshot after a revision conflict\")\n            raise AssertionError(\"bounded scoped-clear retry did not return or raise\")\n        current = self.get_memory_data(agent_name, user_id=user_id)\n        cleared_memory = copy.deepcopy(current)\n        cleared_memory[\"facts\"] = []\n        if not self._save_memory_to_file(cleared_memory, agent_name, user_id=user_id, expected_revision=int(current.get(\"revision\") or 0)):\n            raise OSError(\"Failed to save cleared memory data\")\n        return cleared_memory\n\n    def clear_all_memory_data(self, *, user_id: str | None = None) -> dict[str, Any]:\n        \"\"\"Clear global summaries and every agent fact bucket for one user.\"\"\"\n        if getattr(type(self._storage), \"clear_all\", None) is not MemoryStorage.clear_all:\n            return self._storage.clear_all(user_id=user_id)\n        current = self.get_memory_data(user_id=user_id)\n        cleared_memory = create_empty_memory()\n        if not self._save_memory_to_file(\n            cleared_memory,\n            user_id=user_id,\n            expected_revision=int(current.get(\"revision\") or 0),\n        ):\n            raise OSError(\"Failed to save cleared memory data\")\n        return cleared_memory\n\n    def create_memory_fact(self, content: str, category: str = \"context\", confidence: float = 0.5, agent_name: str | None = None, *, user_id: str | None = None) -> tuple[dict[str, Any], str | None]:\n        \"\"\"Create a new fact, persist it, and return ``(updated_memory, fact_id)``.","sourceCodeStart":866,"sourceCodeEnd":902,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py#L866-L902","documentation":"Raised by clear_memory_data on the legacy save path when _save_memory_to_file returns False after building a facts-empty copy of the current memory. The apply_changes fast path retries revision conflicts up to 3 times; this OSError means either that path is unavailable (legacy storage) and the single save attempt failed, or a plain I/O failure occurred.","triggerScenarios":"Calling clear/forget-memory for one agent on the legacy file backend while the memory file cannot be written (permissions, full disk), or a concurrent update changed the file revision between get_memory_data() and the conditional save, since the legacy path has no retry loop.","commonSituations":"Memory directory made read-only after a container restart, NFS/overlayfs rename failures, or a background memory-update job racing a user-initiated 'clear agent memory' action.","solutions":["Retry the clear operation — a lost revision race is transient and the next attempt re-reads the current revision","Fix write permissions on the memory storage directory for the Gateway process user","Check disk space and that the directory is not on a read-only mount","Use a storage backend that overrides apply_changes so clears retry revision conflicts automatically (3 attempts)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    memory.clear_memory_data(agent_name=agent)\nexcept OSError:\n    time.sleep(0.2)\n    memory.clear_memory_data(agent_name=agent)  # re-reads current revision","preventionTips":["Pause background memory-update jobs before issuing clears","Monitor disk space and permissions on the memory data volume"],"tags":["memory","deermem","persistence","clear","io"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}