MemPalace/mempalace · error · ValueError

update requires at least one of documents, metadatas, embedd

Error message

update requires at least one of documents, metadatas, embeddings

What it means

Raised by QdrantCollection.update() when documents, metadatas and embeddings are all None. update() performs a read-merge-write; with nothing to merge it would be a no-op that still round-trips to the server, so the API requires at least one field to change.

Source

Thrown at mempalace/backends/qdrant.py:861

        for doc_id, doc, meta, vector in zip(ids, documents, metadatas, vectors):
            points.append(
                {
                    "id": _point_id(doc_id),
                    "vector": vector,
                    "payload": {
                        _PAYLOAD_ID: str(doc_id),
                        _PAYLOAD_DOCUMENT: str(doc),
                        _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 = []

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Guard before calling: if documents is metadatas is embeddings is None: return (nothing to update)
  2. If the intent was deletion, call delete() instead
  3. If the intent was a no-op touch of updated_at, do it explicitly with metadatas (merge same metadata)
  4. Audit the caller building the kwargs dict — usually an empty patch should be short-circuited earlier

Example fix

# before
 updates = {k: v for k, v in patch.items() if k in ("documents","metadatas","embeddings")}
 collection.update(ids=ids, **updates)  # empty patch -> ValueError
// after
 if not any(updates.get(k) is not None for k in ("documents","metadatas","embeddings")):
     return  # nothing to update
 collection.update(ids=ids, **updates)
Defensive patterns

Strategy: validation

Validate before calling

if documents is None and metadatas is None and embeddings is None:
    return  # nothing to update

Prevention

When it happens

Trigger: Calling update(ids=my_ids) with no other kwargs — often from generic code that builds kwargs dynamically and ends up with all-None values (e.g. an update dict where every optional field was absent).

Common situations: A generic CRUD layer forwarding user input where all optional fields were omitted; a partial-update helper that receives an empty patch dict; conditional code paths that compute new values but a branch leaves everything None.

Related errors


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