bytedance/deer-flow · error · ValueError

memory_data

Error message

memory_data

What it means

MemoryUpdater.import_memory_data() first checks that the incoming memory_data is a dict; anything else (list, string, null, number) raises this minimal ValueError. Import merges sections ('user', 'history') into an empty template and upserts facts, so a non-object root has no meaningful interpretation and is rejected before any deepcopy or storage write.

Source

Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:815

    ) -> bool:
        """Persist memory data via the injected storage."""
        kwargs: dict[str, Any] = {"user_id": user_id}
        if expected_revision is not None:
            kwargs["expected_revision"] = expected_revision
        return self._storage.save(memory_data, agent_name, **kwargs)

    def get_memory_data(self, agent_name: str | None = None, *, user_id: str | None = None) -> dict[str, Any]:
        """Get the current memory data via the injected storage."""
        return self._storage.load(agent_name, user_id=user_id)

    def reload_memory_data(self, agent_name: str | None = None, *, user_id: str | None = None) -> dict[str, Any]:
        """Reload memory data via the injected storage."""
        return self._storage.reload(agent_name, user_id=user_id)

    def import_memory_data(self, memory_data: dict[str, Any], agent_name: str | None = None, *, user_id: str | None = None) -> dict[str, Any]:
        """Persist imported memory data via the injected storage."""
        if not isinstance(memory_data, dict):
            raise ValueError("memory_data")
        memory_data = copy.deepcopy(memory_data)
        empty = create_empty_memory()
        for section in ("user", "history"):
            incoming_section = memory_data.get(section, {})
            if not isinstance(incoming_section, dict):
                raise ValueError(f"memory_data.{section}")
            complete_section = copy.deepcopy(empty[section])
            for key, value in incoming_section.items():
                if key in complete_section and isinstance(complete_section[key], dict) and isinstance(value, dict):
                    complete_section[key].update(copy.deepcopy(value))
                else:
                    complete_section[key] = copy.deepcopy(value)
            memory_data[section] = complete_section
        if agent_name is not None and getattr(type(self._storage), "apply_changes", None) is not MemoryStorage.apply_changes:
            current = self.get_memory_data(agent_name, user_id=user_id)
            incoming_facts = copy.deepcopy(memory_data.get("facts", []))
            if not isinstance(incoming_facts, list) or any(not isinstance(fact, dict) for fact in incoming_facts):
                raise ValueError("memory_data.facts")

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Wrap list payloads: import_memory_data({'facts': [...fact dicts...]}, agent_name=...).
  2. Validate the parsed root type at the HTTP boundary (pydantic root model typed as dict).
  3. Check for a version field in exported files before importing and convert old formats to the current object shape.

Example fix

# before
updater.import_memory_data([fact1, fact2], agent_name=a)

# after
updater.import_memory_data({"facts": [fact1, fact2], "user": {}, "history": {}}, agent_name=a)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(memory_data, dict):
    if isinstance(memory_data, list):
        memory_data = {"facts": memory_data}
    else:
        raise HTTPException(400, "memory import payload must be a JSON object")
updater.import_memory_data(memory_data, agent_name=agent_name)

Type guard

def is_memory_document(value: object) -> TypeGuard[dict[str, Any]]:
    return isinstance(value, dict)

Prevention

When it happens

Trigger: import_memory_data(json.loads(raw)) where raw is a JSON array of facts or a bare string; passing a list of fact dicts directly; forwarding a request body that failed to be parsed into an object.

Common situations: Importing an exported memory file whose format changed between versions; a UI upload endpoint sending a JSON array; API clients wrapping memory in the wrong envelope.

Related errors


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