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
- Wrap list payloads: import_memory_data({'facts': [...fact dicts...]}, agent_name=...).
- Validate the parsed root type at the HTTP boundary (pydantic root model typed as dict).
- 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
- Type the import endpoint's body as a dict/TypedDict via pydantic.
- Version your export format and convert old formats before importing.
- Wrap list-of-facts uploads in {'facts': [...]} explicitly.
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
- memory_data.{section}
- memory_data.facts
- retrieval fact.id must be a non-empty string
- retrieval fact.content must be a non-empty string
- unsupported FTS5 retrieval mode: {mode}
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/4eddcdd370fc08d7.
Report an issue: GitHub.