Skip to content

[BUG] MCP search_memory_facts fails with 'Unable to serialize unknown type: <class neo4j.time.DateTime>' #1438

@maui314159

Description

@maui314159

Summary

The MCP server's search_memory_facts tool consistently returns:

Error searching facts: Unable to serialize unknown type: <class 'neo4j.time.DateTime'>

against a Neo4j-backed graph with non-trivial fact density. search_nodes works fine on the same graph; the failure is specific to fact (edge) retrieval.

Reproduction

Tested on:

  • graphiti HEAD = 9cdcc93 (Apr 22, 2026)
  • Neo4j community 5.x via neo4j:community Apple-container image
  • mcp_server/src/utils/formatting.py unchanged from 375023b
  • Group has ~5,000 RELATES_TO edges populated by add_episode_bulk runs over the past 2 months
mcp__graphiti-pe__search_memory_facts(
    query="Payday Netchex add-on synergy",
    group_ids=["gcc_deals"],
    max_facts=3,
)
# → {"error": "Error searching facts: Unable to serialize unknown type: <class 'neo4j.time.DateTime'>"}

Failure is consistent across queries; it's not group-specific or query-specific.

Expected

search_memory_facts returns a FactSearchResponse with created_at / valid_at / invalid_at / expired_at rendered as ISO 8601 strings (matching the behavior of search_nodes and get_entity_edge).

Root cause hypothesis

mcp_server/src/utils/formatting.py:format_fact_result calls:

edge.model_dump(mode='json', exclude={'fact_embedding'})

Pydantic's mode='json' correctly serializes datetime.datetime, but not neo4j.time.DateTime. The fact that this fails for fact search but not node search suggests at least one search-path-internal EntityEdge construction is bypassing graphiti_core.edges.get_entity_edge_from_record (which calls parse_db_date to convert neo4j.time.DateTime → datetime).

The proper fix is upstream of the formatter — every EntityEdge constructor in the search path should funnel through get_entity_edge_from_record (or equivalently call parse_db_date on temporal fields). Defensive coercion in the formatter is a reasonable second line of defense at the API boundary.

Why this may have flown under the radar

Proposed fix

PR forthcoming with a defensive fix in format_fact_result that coerces neo4j.time.{DateTime,Date} → native datetime.datetime before model_dump. Description of that PR will note that the right long-term fix is upstream of the formatter.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions