{"record":{"id":"299348992a1f89fc","repo":"bytedance/deer-flow","slug":"agent-name-is-required-to-delete-a-fact","errorCode":null,"errorMessage":"agent_name is required to delete a fact","messagePattern":"agent_name is required to delete a fact","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py","lineNumber":1345,"sourceCode":"        return self.apply_changes(\n            {\"upserts\": [incoming], \"upsertRevisions\": {fact_id: expected_fact_revision}},\n            user_id=user_id,\n            agent_name=agent_name,\n            expected_manifest_revision=expected_manifest_revision,\n            allow_manifest_rebase=True,\n        )\n\n    def delete_fact(\n        self,\n        fact_id: str,\n        *,\n        user_id: str | None = None,\n        agent_name: str | None = None,\n        expected_manifest_revision: int | None = None,\n        expected_fact_revision: int | None = None,\n    ) -> dict[str, Any]:\n        if agent_name is None:\n            raise ValueError(\"agent_name is required to delete a fact\")\n        return self.apply_changes(\n            {\n                \"deletes\": [fact_id],\n                \"deleteRevisions\": ({fact_id: expected_fact_revision} if expected_fact_revision is not None else None),\n            },\n            user_id=user_id,\n            agent_name=agent_name,\n            expected_manifest_revision=expected_manifest_revision,\n            allow_manifest_rebase=True,\n        )\n\n    def get_summaries(\n        self,\n        *,\n        user_id: str | None = None,\n        agent_name: str | None = None,\n    ) -> dict[str, Any]:\n        document = self.load(agent_name, user_id=user_id)","sourceCodeStart":1327,"sourceCodeEnd":1363,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py#L1327-L1363","documentation":"MemoryStorage.delete_fact() requires agent_name for the same reason as upsert_fact: the delete is applied via apply_changes against the agent-scoped fact file. The guard fires before the change set is built, so nothing is locked or written.","triggerScenarios":"storage.delete_fact('fact_123') or with only user_id, from a generic 'forget fact' path that received just an id.","commonSituations":"UI 'delete memory' button that carries only the fact id; cleanup scripts iterating ids harvested from exports; a caller assuming user-global fact deletion.","solutions":["Pass the owning agent: storage.delete_fact(fact_id, agent_name=agent_name, user_id=user_id).","Store agent_name alongside fact_id whenever you persist references to facts (e.g. in UI state or search results).","For bulk cleanup, iterate agents and call delete_fact per scope rather than hoping for a global delete."],"exampleFix":"# before\nstorage.delete_fact(fact_id, user_id=user_id)\n\n# after\nstorage.delete_fact(fact_id, agent_name=agent_name, user_id=user_id)","handlingStrategy":"validation","validationCode":"if agent_name is None:\n    raise HTTPException(400, \"agent_name required\")\nstorage.delete_fact(fact_id, agent_name=agent_name, user_id=user_id)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Persist (agent_name, fact_id) pairs, never bare fact ids, in UI state and exports.","Route delete requests through the same scoping metadata used at creation."],"tags":["memory","scoping","validation","deermem"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}