MemPalace/mempalace · error · ValueError
metadatas length {len(metadatas)} does not match ids length
Error message
metadatas length {len(metadatas)} does not match ids length {n} What it means
Raised by sqlite_exact's `_validate_write_batch`: the optional `metadatas` list was supplied but its length differs from `len(ids)`. Metadatas is optional (None is fine), but once present it must pair 1:1 with ids so each stored row gets the right metadata dict.
Source
Thrown at mempalace/backends/sqlite_exact.py:246
if not any(_matches_where_document(document, clause) for clause in value or []):
return False
continue
raise UnsupportedFilterError(f"where_document operator {key!r} not supported")
return True
def _validate_write_batch(
*,
documents: list[str],
ids: list[str],
metadatas: Optional[list[dict]],
embeddings: Optional[list[list[float]]],
) -> None:
n = len(ids)
if len(documents) != n:
raise ValueError(f"documents length {len(documents)} does not match ids length {n}")
if metadatas is not None and len(metadatas) != n:
raise ValueError(f"metadatas length {len(metadatas)} does not match ids length {n}")
if embeddings is not None and len(embeddings) != n:
raise ValueError(f"embeddings length {len(embeddings)} does not match ids length {n}")
class _SQLiteExactHandle:
def __init__(
self,
conn: sqlite3.Connection,
lock: threading.RLock,
palace_path: str,
*,
read_only: bool = False,
immutable: bool = False,
):
self.conn = conn
self.lock = lock
self.palace_path = palace_path
self.read_only = read_onlyView on GitHub (pinned to 06cb6987f0)
Solutions
- If all rows share metadata, repeat it: `metadatas=[meta] * len(ids)`.
- Fill missing per-id metadata with `{}` instead of dropping entries: `metadatas = [per_id.get(i, {}) for i in ids]`.
- Add a pre-call assert `len(metadatas) == len(ids)` in dev builds and tests.
Example fix
# before
col.upsert(ids=ids, documents=docs, metadatas=[{"wing": "alice"}]) # 1 != N
# after
col.upsert(ids=ids, documents=docs, metadatas=[{"wing": "alice"}] * len(ids)) Defensive patterns
Strategy: validation
Validate before calling
def align_metadatas(ids, metadatas):
if metadatas is None:
return None
if len(metadatas) != len(ids):
raise ValueError(f"metadatas {len(metadatas)} != ids {len(ids)}")
return metadatas Try / catch
try:
col.upsert(ids=ids, documents=docs, metadatas=metas)
except ValueError as e:
if "metadatas length" in str(e):
metas = metas * len(ids) if len(metas) == 1 else [{} for _ in ids]
col.upsert(ids=ids, documents=docs, metadatas=metas) Prevention
- Remember the API takes a LIST of dicts, one per row — never a bare dict.
- Use `[meta] * len(ids)` for shared metadata.
- Default missing per-id metadata to {} instead of dropping entries.
When it happens
Trigger: Calling upsert/add with `metadatas=[...]` shorter or longer than `ids` — commonly one shared metadata dict passed bare instead of repeated per row, or a comprehension that drops entries where metadata is missing.
Common situations: Passing a single metadata dict when the API expects a list (e.g. `metadatas={"wing": "x"}`); building metadatas with `filter(None, ...)` while ids keep all items; merging metadata from a dict keyed by id where some ids have no entry.
Related errors
- documents length {len(documents)} does not match ids length
- embeddings length {len(embeddings)} does not match ids lengt
- metadata key {key!r} clashes with a reserved Milvus field
- metadatas length {len(metadatas)} does not match ids length
- operator {key!r} not supported by sqlite_exact
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/0d0b846eb4be2b1f.
Report an issue: GitHub.