bytedance/deer-flow · error · ValueError

agent_name is required to delete a fact

Error message

agent_name is required to delete a fact

What it means

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.

Source

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

        return self.apply_changes(
            {"upserts": [incoming], "upsertRevisions": {fact_id: expected_fact_revision}},
            user_id=user_id,
            agent_name=agent_name,
            expected_manifest_revision=expected_manifest_revision,
            allow_manifest_rebase=True,
        )

    def delete_fact(
        self,
        fact_id: str,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
        expected_manifest_revision: int | None = None,
        expected_fact_revision: int | None = None,
    ) -> dict[str, Any]:
        if agent_name is None:
            raise ValueError("agent_name is required to delete a fact")
        return self.apply_changes(
            {
                "deletes": [fact_id],
                "deleteRevisions": ({fact_id: expected_fact_revision} if expected_fact_revision is not None else None),
            },
            user_id=user_id,
            agent_name=agent_name,
            expected_manifest_revision=expected_manifest_revision,
            allow_manifest_rebase=True,
        )

    def get_summaries(
        self,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
    ) -> dict[str, Any]:
        document = self.load(agent_name, user_id=user_id)

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Pass the owning agent: storage.delete_fact(fact_id, agent_name=agent_name, user_id=user_id).
  2. Store agent_name alongside fact_id whenever you persist references to facts (e.g. in UI state or search results).
  3. For bulk cleanup, iterate agents and call delete_fact per scope rather than hoping for a global delete.

Example fix

# before
storage.delete_fact(fact_id, user_id=user_id)

# after
storage.delete_fact(fact_id, agent_name=agent_name, user_id=user_id)
Defensive patterns

Strategy: validation

Validate before calling

if agent_name is None:
    raise HTTPException(400, "agent_name required")
storage.delete_fact(fact_id, agent_name=agent_name, user_id=user_id)

Prevention

When it happens

Trigger: storage.delete_fact('fact_123') or with only user_id, from a generic 'forget fact' path that received just an id.

Common situations: UI 'delete memory' button that carries only the fact id; cleanup scripts iterating ids harvested from exports; a caller assuming user-global fact deletion.

Related errors


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