bytedance/deer-flow · error · ValueError

Duplicate fact ids are not allowed in deletes

Error message

Duplicate fact ids are not allowed in deletes

What it means

Error "Duplicate fact ids are not allowed in deletes" thrown in bytedance/deer-flow.

Source

Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py:759

                raise ValueError(f"Duplicate fact id {fact_id!r} in upserts")
            if agent_name is None:  # guarded above
                raise ValueError("agent_name is required for fact repository changes")
            existing, fact_path = self._read_fact(path, fact_id, user_id=user_id, agent_name=agent_name)
            if upsert_revisions is not None and fact_id in upsert_revisions:
                expected_fact_revision = upsert_revisions[fact_id]
                if expected_fact_revision is None and existing is not None:
                    raise MemoryFactRevisionConflict(f"Fact {fact_id!r} must not already exist")
                if expected_fact_revision is not None:
                    actual_fact_revision = None if existing is None else existing.get("revision")
                    if actual_fact_revision != expected_fact_revision:
                        raise MemoryFactRevisionConflict(f"Expected fact {fact_id!r} revision {expected_fact_revision}, found {actual_fact_revision}")
            normalized = _normalize_fact(candidate, scope=scope, existing=existing)
            if existing != normalized:
                prepared[fact_id] = (normalized, existing, fact_path)

        delete_ids = [str(fact_id) for fact_id in deletes]
        if len(delete_ids) != len(set(delete_ids)):
            raise ValueError("Duplicate fact ids are not allowed in deletes")
        removals: dict[str, tuple[dict[str, Any], Path]] = {}
        for fact_id in delete_ids:
            if fact_id in prepared:
                raise ValueError(f"Fact {fact_id!r} cannot be upserted and deleted together")
            if agent_name is None:  # guarded above
                raise ValueError("agent_name is required for fact repository changes")
            existing, fact_path = self._read_fact(path, fact_id, user_id=user_id, agent_name=agent_name)
            if existing is None:
                continue
            if delete_revisions and fact_id in delete_revisions and delete_revisions[fact_id] != existing.get("revision"):
                raise MemoryFactRevisionConflict(f"Expected fact {fact_id!r} revision {delete_revisions[fact_id]}, found {existing.get('revision')}")
            removals[fact_id] = (existing, fact_path)

        base = current_memory or create_empty_memory()
        user_section = copy.deepcopy(base.get("user", {}))
        history_section = copy.deepcopy(base.get("history", {}))
        if summaries is not None:
            if not isinstance(summaries, dict):

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Deduplicate the deletes list; each fact id may appear once.
  2. Fix the client building the change set to unique the ids.

When it happens

Trigger: Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py:759 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/8dd6b5a5db99f599. Report an issue: GitHub.