{"record":{"id":"3355da8392b3580b","repo":"bytedance/deer-flow","slug":"agent-name-is-required-to-get-a-fact","errorCode":null,"errorMessage":"agent_name is required to get a fact","messagePattern":"agent_name is required to get a fact","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py","lineNumber":1197,"sourceCode":"\n    @staticmethod\n    def _scope_kwargs(scope: dict[str, str | None]) -> dict[str, str]:\n        kwargs: dict[str, str] = {}\n        if scope.get(\"userId\") is not None:\n            kwargs[\"user_id\"] = str(scope[\"userId\"])\n        if scope.get(\"agentName\") is not None:\n            kwargs[\"agent_name\"] = str(scope[\"agentName\"])\n        return kwargs\n\n    def get_fact(\n        self,\n        fact_id: str,\n        *,\n        user_id: str | None = None,\n        agent_name: str | None = None,\n    ) -> dict[str, Any] | None:\n        if agent_name is None:\n            raise ValueError(\"agent_name is required to get a fact\")\n        path = self._get_memory_file_path(agent_name, user_id=user_id)\n        key = self._cache_key(agent_name, user_id=user_id)\n        legacy_path = self._legacy_agent_memory_path(path, agent_name)\n        notifications: list[RetrievalNotification] = []\n        with self._scope_lock(key), _process_file_lock(path.parent / \".memory.lock\", float(getattr(self._config, \"file_lock_timeout_seconds\", 10))):\n            self._recover_if_needed(path)\n            if legacy_path.exists():\n                _, _, notifications = self._migrate_locked(path, agent_name, user_id=user_id, include_global=False)\n            fact, _ = self._read_fact(path, fact_id, user_id=user_id, agent_name=agent_name)\n        self._dispatch_retrieval_notifications(notifications, user_id=user_id, agent_name=agent_name)\n        return copy.deepcopy(fact)\n\n    def list_facts(\n        self,\n        *,\n        user_id: str | None = None,\n        agent_name: str | None = None,\n        filters: dict[str, Any] | None = None,","sourceCodeStart":1179,"sourceCodeEnd":1215,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py#L1179-L1215","documentation":"MemoryStorage.get_fact() requires agent_name because facts live in per-agent memory files (path is derived from agent_name and user_id); there is no global fact lookup. The ValueError fires immediately, before path resolution, locking, or legacy migration, so a failed call has no side effects.","triggerScenarios":"storage.get_fact('fact_123') or storage.get_fact('fact_123', user_id=u) with agent_name omitted while routing a generic 'read fact by id' API that assumed global ids.","commonSituations":"Building a generic fact-inspection endpoint that only receives fact_id; refactoring a caller that previously loaded facts via list_facts(user-only) and now tries get_fact without the agent scope; passing agent_name=None as a sentinel for 'any agent'.","solutions":["Supply the agent scope: storage.get_fact(fact_id, agent_name=agent_name, user_id=user_id).","If you only know the fact id, first locate the owning agent with list_facts(agent_name=..., filters={'id': fact_id}) per known agent, or maintain an id->agent index.","Fix API contracts so fact ids are always handled together with their agent scope."],"exampleFix":"# before\nfact = storage.get_fact(fact_id, user_id=user_id)\n\n# after\nfact = storage.get_fact(fact_id, agent_name=agent_name, user_id=user_id)","handlingStrategy":"validation","validationCode":"if agent_name is None:\n    raise HTTPException(400, \"fact lookup requires agent_name\")\nfact = storage.get_fact(fact_id, agent_name=agent_name, user_id=user_id)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat (agent_name, fact_id) as the composite key everywhere facts are referenced.","Carry agent_name alongside fact_id in search results and UI state.","Expose fact ids only through APIs that also expose their agent scope."],"tags":["memory","scoping","validation","deermem"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}