{"record":{"id":"8dd6b5a5db99f599","repo":"bytedance/deer-flow","slug":"duplicate-fact-ids-are-not-allowed-in-deletes","errorCode":null,"errorMessage":"Duplicate fact ids are not allowed in deletes","messagePattern":"Duplicate fact ids are not allowed in deletes","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py","lineNumber":759,"sourceCode":"                raise ValueError(f\"Duplicate fact id {fact_id!r} in upserts\")\n            if agent_name is None:  # guarded above\n                raise ValueError(\"agent_name is required for fact repository changes\")\n            existing, fact_path = self._read_fact(path, fact_id, user_id=user_id, agent_name=agent_name)\n            if upsert_revisions is not None and fact_id in upsert_revisions:\n                expected_fact_revision = upsert_revisions[fact_id]\n                if expected_fact_revision is None and existing is not None:\n                    raise MemoryFactRevisionConflict(f\"Fact {fact_id!r} must not already exist\")\n                if expected_fact_revision is not None:\n                    actual_fact_revision = None if existing is None else existing.get(\"revision\")\n                    if actual_fact_revision != expected_fact_revision:\n                        raise MemoryFactRevisionConflict(f\"Expected fact {fact_id!r} revision {expected_fact_revision}, found {actual_fact_revision}\")\n            normalized = _normalize_fact(candidate, scope=scope, existing=existing)\n            if existing != normalized:\n                prepared[fact_id] = (normalized, existing, fact_path)\n\n        delete_ids = [str(fact_id) for fact_id in deletes]\n        if len(delete_ids) != len(set(delete_ids)):\n            raise ValueError(\"Duplicate fact ids are not allowed in deletes\")\n        removals: dict[str, tuple[dict[str, Any], Path]] = {}\n        for fact_id in delete_ids:\n            if fact_id in prepared:\n                raise ValueError(f\"Fact {fact_id!r} cannot be upserted and deleted together\")\n            if agent_name is None:  # guarded above\n                raise ValueError(\"agent_name is required for fact repository changes\")\n            existing, fact_path = self._read_fact(path, fact_id, user_id=user_id, agent_name=agent_name)\n            if existing is None:\n                continue\n            if delete_revisions and fact_id in delete_revisions and delete_revisions[fact_id] != existing.get(\"revision\"):\n                raise MemoryFactRevisionConflict(f\"Expected fact {fact_id!r} revision {delete_revisions[fact_id]}, found {existing.get('revision')}\")\n            removals[fact_id] = (existing, fact_path)\n\n        base = current_memory or create_empty_memory()\n        user_section = copy.deepcopy(base.get(\"user\", {}))\n        history_section = copy.deepcopy(base.get(\"history\", {}))\n        if summaries is not None:\n            if not isinstance(summaries, dict):","sourceCodeStart":741,"sourceCodeEnd":777,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py#L741-L777","documentation":"Error \"Duplicate fact ids are not allowed in deletes\" thrown in bytedance/deer-flow.","triggerScenarios":"Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py:759 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Deduplicate the deletes list; each fact id may appear once.","Fix the client building the change set to unique the ids."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}