Skip to content

Event-backend sessions refuse metadata keys outside the vector stores' key set after the episode store and semantic memory have written the episode #1796

Description

@edwinyyyu

What happens

Measured on main at ad8ff24 through POST /api/v2/memories into an event-backend session, with the real episode store, segment store, and semantic storage on SQLite and on PostgreSQL, and SQLiteVectorStore. The same holds on SQLite and PostgreSQL:

metadata status episode store semantic memory sets segment store vector store
{"userId": "v"} 500 written written (3) written nothing
{"_x": "v"} 500 written written (3) nothing nothing
{"k": "v"} 200 written written (3) written written

Store by store, through each store's own code, the vector stores refuse a key that is not lowercase letters, digits, and underscores of at most 32 bytes: userId, a-b, a.b, a b, the empty key, 33 characters, and é alike (SQLiteVectorStore, SQLiteVecVectorStore, Qdrant, and Milvus). A collection whose declared user properties hold such a key cannot be created. The episode store and the segment store keep every such key; the PostgreSQL stores refuse only a key with U+0000.

Why

  • The request takes any string as a metadata key (packages/common/src/memmachine_common/api/spec.py:474), and every string metadata value becomes a filterable property under its key (packages/server/src/memmachine_server/episodic_memory/episodic_memory.py:225-229).
  • The event backend refuses a key that starts with an underscore when it builds the event (packages/server/src/memmachine_server/episodic_memory/long_term_memory/long_term_memory.py:818-830), and a vector store record refuses a key outside its key set (packages/server/src/memmachine_server/common/vector_store/data_types.py:135-146). The record is built after the segment store has written the segment (packages/server/src/memmachine_server/episodic_memory/event_memory/event_memory.py:274-292).
  • MemMachine.add_episodes writes the episode store, episodic memory, and semantic memory concurrently (packages/server/src/memmachine_server/main/memmachine.py:795-819), so the episode store and semantic memory have written the episode by the time the event backend refuses it.

Expected

An episode is written to every store or to none: the event backend accepts every key the request accepts, or the request refuses the key with 422 before any store writes.

Fix

Not in #1792, since it needs a decision. #1383 was closed with "Internally changing to use UUID would be better. Externally can allow a wider set.", which points at mapping user keys to internal names in the event backend so that it accepts what the request accepts. Until then, the request could refuse these keys with 422.

🤖 Written by Claude Code (Claude Opus 5.5) on behalf of @edwinyyyu.

Activity

  1. added theissue type on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions