MemPalace/mempalace · error · ValueError

{label} length {len(value)} does not match ids length {n}

Error message

{label} length {len(value)} does not match ids length {n}

What it means

PgVectorCollection.update() validates that every provided parallel array (documents, metadatas, embeddings) has the same length as the ids list before touching the database. If any one of them differs, it raises this ValueError immediately, so no partial update can be written. This mirrors the batch-invariants enforced by the base backend interface and ChromaDB-style APIs.

Source

Thrown at mempalace/backends/pgvector.py:1005

                "embedding": vector,
                "updated_at": _utcnow(),
            }
            for doc_id, doc, meta, vector in zip(ids, documents, metadatas, vectors)
        ]
        self._client.upsert_rows(self._table, rows)
        self._backend._write_marker(self._palace, self._config)

    def update(self, *, ids, documents=None, metadatas=None, embeddings=None):
        if documents is None and metadatas is None and embeddings is None:
            raise ValueError("update requires at least one of documents, metadatas, embeddings")
        n = len(ids)
        for label, value in (
            ("documents", documents),
            ("metadatas", metadatas),
            ("embeddings", embeddings),
        ):
            if value is not None and len(value) != n:
                raise ValueError(f"{label} length {len(value)} does not match ids length {n}")
        existing = self.get(ids=ids, include=["documents", "metadatas", "embeddings"])
        by_id = {
            rid: (existing.documents[i], existing.metadatas[i], existing.embeddings[i])
            for i, rid in enumerate(existing.ids)
            if existing.embeddings is not None
        }
        out_ids, out_docs, out_metas, out_embeddings = [], [], [], []
        for idx, doc_id in enumerate(ids):
            if doc_id not in by_id:
                continue
            prev_doc, prev_meta, prev_embedding = by_id[doc_id]
            out_ids.append(doc_id)
            out_docs.append(documents[idx] if documents is not None else prev_doc)
            meta = dict(prev_meta or {})
            if metadatas is not None:
                meta.update(metadatas[idx] or {})
            out_metas.append(meta)
            out_embeddings.append(embeddings[idx] if embeddings is not None else prev_embedding)

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Make all arrays the same length before calling update(), e.g. assert len(ids) == len(documents or ids) == len(metadatas or ids).
  2. Build the batch as a single list of records ({id, document, metadata, embedding}) and derive the parallel arrays with zip(*(...)) so they cannot diverge.
  3. Pass None for arrays you are not updating instead of an empty or stale list.

Example fix

# before
collection.update(ids=ids, documents=new_docs, metadatas=metas)  # len mismatch

# after
assert len(ids) == len(new_docs) == len(metas)
collection.update(ids=ids, documents=new_docs, metadatas=metas)
Defensive patterns

Strategy: validation

Validate before calling

def safe_update(col, ids, documents=None, metadatas=None, embeddings=None):
    n = len(ids)
    for name, arr in (("documents", documents), ("metadatas", metadatas), ("embeddings", embeddings)):
        if arr is not None and len(arr) != n:
            raise ValueError(f"{name} length {len(arr)} != ids length {n}")
    return col.update(ids=ids, documents=documents, metadatas=metadatas, embeddings=embeddings)

Type guard

def is_aligned_batch(ids, **arrays) -> bool:
    return all(v is None or len(v) == len(ids) for v in arrays.values())

Try / catch

try:
    col.update(ids=ids, documents=docs, metadatas=metas)
except ValueError as e:
    if "does not match ids length" in str(e):
        logger.error("batch misaligned", len_ids=len(ids))
        raise

Prevention

When it happens

Trigger: Calling collection.update(ids=["a","b"], documents=["one doc"]) or update(ids=["a"], metadatas=[m1, m2], embeddings=[[...]]) — any call where len(documents), len(metadatas), or len(embeddings) differs from len(ids).

Common situations: Building the ids list and the metadata list in separate loops that append under different conditions; slicing one array but not another (docs[:-1] vs ids); reusing a batch-upsert helper that drops malformed entries from only one array before calling update().

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/e63bd3017b03df0f. Report an issue: GitHub.