bytedance/deer-flow · error · MemoryStorageCorruption

Hash mismatch for canonical fact {fact_id!r}

Error message

Hash mismatch for canonical fact {fact_id!r}

What it means

Error "Hash mismatch for canonical fact {fact_id!r}" thrown in bytedance/deer-flow.

Source

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

        """Build the compatibility document without persisting facts in JSON."""
        legacy_facts = memory_file.get("facts")
        contains_owned_legacy_facts = isinstance(legacy_facts, dict) or (isinstance(legacy_facts, list) and bool(legacy_facts))
        if contains_owned_legacy_facts and not allow_legacy_facts:
            raise MemoryStorageCorruption(f"Legacy facts in {path} require explicit migrate(user_id=..., agent_name=...)")
        if isinstance(legacy_facts, list):
            facts = copy.deepcopy(legacy_facts) if agent_name is not None else []
        elif isinstance(legacy_facts, dict):
            facts = []
            if agent_name is not None:
                for fact_id, entry in legacy_facts.items():
                    if not isinstance(entry, dict) or not isinstance(entry.get("path"), str):
                        raise MemoryStorageCorruption(f"Invalid legacy manifest entry for fact {fact_id!r}")
                    fact_path = _safe_relative_path(path.parent, entry["path"], label="legacy fact")
                    fact = _parse_fact_markdown(fact_path)
                    if str(fact.get("id")) != str(fact_id):
                        raise MemoryStorageCorruption(f"Legacy manifest id mismatch for fact {fact_id!r}")
                    if entry.get("contentHash") and entry.get("contentHash") != _content_hash(fact_path.read_bytes()):
                        raise MemoryStorageCorruption(f"Hash mismatch for canonical fact {fact_id!r}")
                    facts.append(fact)
        elif legacy_facts is None:
            facts = self._load_agent_facts(path, agent_name, user_id=user_id)
        else:
            raise MemoryStorageCorruption(f"Legacy facts in {path} must be a list or mapping")
        result = {key: copy.deepcopy(value) for key, value in memory_file.items() if key != "facts"}
        result.setdefault("revision", 0)
        result["facts"] = facts
        return result

    def _read_document(self, path: Path, agent_name: str | None, *, user_id: str | None) -> dict[str, Any]:
        memory_file = self._load_memory_file(path)
        if memory_file is None:
            result = create_empty_memory()
            result["facts"] = self._load_agent_facts(path, agent_name, user_id=user_id)
            return result
        return self._document_from_memory_file(memory_file, path, agent_name, user_id=user_id)

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. The canonical fact was modified out-of-band; restore the original content or accept the change by re-hashing through the API.
  2. Check for external editors touching the memory directory.

When it happens

Trigger: Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py:962 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/57f5667a00d522fd. Report an issue: GitHub.