What happens
Measured on main at ad8ff24, one value at a time through each store's own code, on SQLite and PostgreSQL where a store supports both, with Qdrant 1.17.0 and Milvus 2.6.24 and Milvus Lite. The value is a string property value of random characters, 3,000 to 1,000,000 long:
| store |
metadata value |
producer |
metadata value whose key a semantic set type names (producer_id) |
| episode store, SQLite |
stored |
stored |
stored |
| episode store, PostgreSQL |
stored |
refused from 3,000 characters (index row size 3016 exceeds btree version 4 maximum 2704) |
stored |
| segment store, SQLite and PostgreSQL |
stored |
stored |
stored |
| semantic memory, SQLite |
not received |
stored in a set id |
stored in a set id |
| semantic memory, PostgreSQL |
not received |
refused from 3,000 characters (btree index row size on the set id) |
refused from 3,000 characters |
SQLiteVectorStore, SQLiteVecVectorStore, Qdrant, Milvus Lite |
stored |
stored |
stored |
MilvusVectorStore, 2.6.24 |
refused from 65,000 characters (the length (65552) of json field (properties) exceeds max length (65536)) |
refused from 70,000 characters |
refused from 65,000 characters |
Through POST /api/v2/memories on PostgreSQL with metadata {"producer_id": <3,000 characters>}: 500, with the episode in the episode store, segment store, and vector store and in no semantic set.
Why
- The request takes strings of any length.
- The PostgreSQL episode store indexes
producer_id, producer_role, and produced_for_id with B-trees (packages/server/src/memmachine_server/common/episode_store/episode_sqlalchemy_store.py:110-121), and the semantic storages index set ids, which embed the producer and tagged metadata values (packages/server/src/memmachine_server/semantic_memory/semantic_session_manager.py:446-460, packages/server/src/memmachine_server/semantic_memory/storage/sqlalchemy_pgvector_semantic.py:158-171). A B-tree entry holds at most 2,704 bytes after compression.
- Milvus keeps a record's properties in one JSON field, whose length its server configuration bounds.
MemMachine.add_episodes writes the stores concurrently (packages/server/src/memmachine_server/main/memmachine.py:795-819).
Expected
The request refuses a string that some store cannot hold with 422 before any store writes.
Fix
Not in #1792, since it needs a decision on the limits: the B-tree bound is per indexed field and counts compressed bytes, and Milvus's bound is a server setting, so a fixed length in the request either refuses what a store holds or admits what another refuses.
🤖 Written by Claude Code (Claude Opus 5.5) on behalf of @edwinyyyu.
What happens
Measured on
mainat ad8ff24, one value at a time through each store's own code, on SQLite and PostgreSQL where a store supports both, with Qdrant 1.17.0 and Milvus 2.6.24 and Milvus Lite. The value is a string property value of random characters, 3,000 to 1,000,000 long:producerproducer_id)index row size 3016 exceeds btree version 4 maximum 2704)SQLiteVectorStore,SQLiteVecVectorStore, Qdrant, Milvus LiteMilvusVectorStore, 2.6.24the length (65552) of json field (properties) exceeds max length (65536))Through
POST /api/v2/memorieson PostgreSQL with metadata{"producer_id": <3,000 characters>}: 500, with the episode in the episode store, segment store, and vector store and in no semantic set.Why
producer_id,producer_role, andproduced_for_idwith B-trees (packages/server/src/memmachine_server/common/episode_store/episode_sqlalchemy_store.py:110-121), and the semantic storages index set ids, which embed the producer and tagged metadata values (packages/server/src/memmachine_server/semantic_memory/semantic_session_manager.py:446-460,packages/server/src/memmachine_server/semantic_memory/storage/sqlalchemy_pgvector_semantic.py:158-171). A B-tree entry holds at most 2,704 bytes after compression.MemMachine.add_episodeswrites the stores concurrently (packages/server/src/memmachine_server/main/memmachine.py:795-819).Expected
The request refuses a string that some store cannot hold with 422 before any store writes.
Fix
Not in #1792, since it needs a decision on the limits: the B-tree bound is per indexed field and counts compressed bytes, and Milvus's bound is a server setting, so a fixed length in the request either refuses what a store holds or admits what another refuses.
🤖 Written by Claude Code (Claude Opus 5.5) on behalf of @edwinyyyu.