{"record":{"id":"0f06f64275a7c827","repo":"bytedance/deer-flow","slug":"delete-fact-not-supported-by-type-self-name","errorCode":null,"errorMessage":"delete_fact not supported by {type(self).__name__}","messagePattern":"delete_fact not supported by (.+?)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/manager.py","lineNumber":418,"sourceCode":"        category: str = \"context\",\n        confidence: float = 0.5,\n        *,\n        agent_name: str | None = None,\n        user_id: str | None = None,\n    ) -> tuple[dict[str, Any], str | None]:\n        \"\"\"Manually add one fact. Returns ``(memory_data, fact_id)`` -- ``fact_id``\n        is None when a storage cap evicted the just-added fact. Default: unsupported.\"\"\"\n        raise NotImplementedError(f\"create_fact not supported by {type(self).__name__}\")\n\n    def delete_fact(\n        self,\n        fact_id: str,\n        *,\n        agent_name: str | None = None,\n        user_id: str | None = None,\n    ) -> dict[str, Any]:\n        \"\"\"Delete one fact by id. Default: unsupported.\"\"\"\n        raise NotImplementedError(f\"delete_fact not supported by {type(self).__name__}\")\n\n    def update_fact(\n        self,\n        fact_id: str,\n        content: str | None = None,\n        category: str | None = None,\n        confidence: float | None = None,\n        *,\n        agent_name: str | None = None,\n        user_id: str | None = None,\n    ) -> dict[str, Any]:\n        \"\"\"Update one fact by id (preserving omitted fields). Default: unsupported.\"\"\"\n        raise NotImplementedError(f\"update_fact not supported by {type(self).__name__}\")\n\n    # B-class: no agent-side caller yet -- signatures only, for future scenarios.\n    # Default no-op so callers can invoke unconditionally without gating. (The\n    # self-serving hooks on_delegation / on_session_end / on_memory_write are\n    # deliberately NOT contracted: no caller, no event source, or subsumed by","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/manager.py#L400-L436","documentation":"MemoryManager.delete_fact raises NotImplementedError as the optional per-fact CRUD default: deleting one fact by id is only meaningful for backends that own discrete, addressable fact records — DeerMem. Remote/no-op backends (noop, mem0, honcho, openviking) inherit the raising default, so calling delete_fact on them is an explicit capability mismatch rather than a runtime failure of the store.","triggerScenarios":"Calling MemoryManager.delete_fact(fact_id, agent_name=..., user_id=...) — via the memory_delete tool in memory.mode: tool, a management API route, or directly — while the configured manager_class does not override it. The fact_id comes from a prior get_memory()/create_fact() response, so it typically surfaces in fact-management UIs after a backend switch.","commonSituations":"A fact-management interface built against deermem being used after config.yaml switched memory.manager_class to mem0/honcho; memory.mode: tool enabled with a remote backend; cleanup scripts iterating fact lists and deleting by id.","solutions":["Switch to a backend implementing fact CRUD (memory.manager_class: deermem) if per-fact deletion is required.","Use the backend's own deletion mechanism (its native API or clearing memory via the supported clear path) instead of delete_fact.","Custom backends: override delete_fact on the MemoryManager subclass.","Hide/disable delete affordances when the backend lacks the capability instead of calling and crashing."],"exampleFix":"# before\nmemory = manager.delete_fact(fact_id, user_id=\"u1\")  # NotImplementedError on remote backends\n\n# after\ntry:\n    memory = manager.delete_fact(fact_id, user_id=\"u1\")\nexcept NotImplementedError:\n    memory = manager.clear_memory(user_id=\"u1\")  # coarse fallback only if acceptable","handlingStrategy":"type-guard","validationCode":"from deerflow.agents.memory.manager import MemoryManager\n\ndef supports_fact_delete(manager: MemoryManager) -> bool:\n    return type(manager).delete_fact is not MemoryManager.delete_fact","typeGuard":"def supports_fact_delete(manager: MemoryManager) -> bool:\n    \"\"\"True when the backend can delete one fact by id.\"\"\"\n    return type(manager).delete_fact is not MemoryManager.delete_fact","tryCatchPattern":"try:\n    memory = manager.delete_fact(fact_id, user_id=uid)\nexcept NotImplementedError as e:\n    raise UnsupportedMemoryOperation(str(e)) from e  # permanent, not retryable","preventionTips":["Disable per-fact delete buttons in management UIs when the backend lacks the primitive.","When switching backends in config.yaml, re-verify fact CRUD workflows still apply.","Prefer clear_memory (where supported) for bulk resets instead of iterating delete_fact."],"tags":["memory","not-implemented","crud","deerflow"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}