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

Raised by QdrantCollection.update() when any of the provided parallel arrays (documents, metadatas, embeddings) has a length different from the ids array. update() merges per-id, so every supplied array must align 1:1 with ids.

Source

Thrown at mempalace/backends/qdrant.py:869

                        _PAYLOAD_METADATA: _jsonable_metadata(meta),
                        "updated_at": _utcnow(),
                    },
                }
            )
        self._client.upsert_points(self._remote_collection, points)
        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:

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Broadcast explicitly: metadatas = [meta] * len(ids) if you meant one value for all rows
  2. Rebuild arrays with zip(ids, ...) so they cannot drift from ids
  3. Add a pre-call assertion: assert all(v is None or len(v) == len(ids) for v in (documents, metadatas, embeddings))
  4. The error message names the offending label — check that array's construction logic first

Example fix

# before
collection.update(ids=ids, metadatas=[{"seen": True}])  # 1 != len(ids)
// after
collection.update(ids=ids, metadatas=[{"seen": True}] * len(ids))
Defensive patterns

Strategy: validation

Validate before calling

assert all(v is None or len(v) == len(ids) for v in (documents, metadatas, embeddings))

Prevention

When it happens

Trigger: Calling update(ids=['a','b','c'], metadatas=[m1]) or similar — e.g. passing a single metadata dict meant for all rows, or building arrays in a loop that appends conditionally so some rows are skipped.

Common situations: Caller passes one shared value instead of a per-id list (scalar/1-element broadcast mistake); array built with a filtered comprehension while ids weren't filtered; off-by-one in chunked update loops.

Related errors


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