{"record":{"id":"9a10b7ef78ce2de0","repo":"bytedance/deer-flow","slug":"failed-to-save-imported-memory-data","errorCode":null,"errorMessage":"Failed to save imported memory data","messagePattern":"Failed to save imported memory data","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py","lineNumber":855,"sourceCode":"            current_by_id = {str(fact.get(\"id\")): fact for fact in current.get(\"facts\", []) if isinstance(fact, dict)}\n            incoming_ids = {str(fact.get(\"id\")) for fact in incoming_facts}\n            self._storage.apply_changes(\n                {\n                    \"upserts\": incoming_facts,\n                    \"upsertRevisions\": {str(fact.get(\"id\")): (int(current_by_id[str(fact.get(\"id\"))].get(\"revision\") or 1) if str(fact.get(\"id\")) in current_by_id else None) for fact in incoming_facts},\n                    \"deletes\": [fact_id for fact_id in current_by_id if fact_id not in incoming_ids],\n                    \"deleteRevisions\": {fact_id: int(fact.get(\"revision\") or 1) for fact_id, fact in current_by_id.items() if fact_id not in incoming_ids},\n                    \"summaries\": {\"user\": copy.deepcopy(memory_data.get(\"user\", {})), \"history\": copy.deepcopy(memory_data.get(\"history\", {}))},\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._storage.load(agent_name, user_id=user_id)\n        if agent_name is None:\n            memory_data[\"facts\"] = []\n        if not self._storage.save(memory_data, agent_name, user_id=user_id):\n            raise OSError(\"Failed to save imported memory data\")\n        return self._storage.load(agent_name, user_id=user_id)\n\n    def clear_memory_data(self, agent_name: str | None = None, *, user_id: str | None = None) -> dict[str, Any]:\n        \"\"\"Clear one selected agent's facts without resetting shared summaries.\"\"\"\n        if agent_name is not None and getattr(type(self._storage), \"apply_changes\", None) is not MemoryStorage.apply_changes:\n            for attempt in range(3):\n                current = self.get_memory_data(agent_name, user_id=user_id) if attempt == 0 else self.reload_memory_data(agent_name, user_id=user_id)\n                facts = [fact for fact in current.get(\"facts\", []) if isinstance(fact, dict)]\n                try:\n                    self._storage.apply_changes(\n                        {\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                    )","sourceCodeStart":837,"sourceCodeEnd":873,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py#L837-L873","documentation":"Raised when the legacy single-file storage path of DeerMem's import returns falsy from storage.save(memory_data, agent_name, user_id). This branch only runs when the storage backend does not override MemoryStorage.apply_changes (i.e. the legacy file backend). A False return means the atomic write/rename to the memory file failed or the expected revision did not match.","triggerScenarios":"import_memory_data on the legacy file storage while the memory file is unwritable (permissions, read-only mount, disk full), the memory directory was deleted mid-run, or a concurrent writer bumped the file revision so the conditional save refused.","commonSituations":"Running the Gateway as a user without write access to the memory data directory, a container with a read-only volume mounted over the memory path, or two concurrent imports/updates racing on the same agent's file.","solutions":["Check filesystem permissions on the DeerMem storage directory (the process user must own or be able to write it)","Retry the import once the concurrent write finishes; the legacy path does not auto-retry revision conflicts","Switch to a storage backend that implements apply_changes (which handles revision conflicts internally) if concurrency is expected","Verify disk space on the volume holding the memory files"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import os\n\ndef storage_writable(path: str) -> bool:\n    return os.access(os.path.dirname(path) or \".\", os.W_OK)","typeGuard":null,"tryCatchPattern":"try:\n    memory.import_memory_data(memory_data, agent_name=agent)\nexcept OSError:\n    # transient revision race or I/O failure; single retry after re-read\n    time.sleep(0.2)\n    memory.import_memory_data(memory_data, agent_name=agent)","preventionTips":["Keep memory storage directories writable by the Gateway process user","Avoid concurrent imports to the same agent; serialize them per agent_name"],"tags":["memory","deermem","persistence","io","import"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}