{"record":{"id":"e63bd3017b03df0f","repo":"MemPalace/mempalace","slug":"label-length-len-value-does-not-match-ids-len-e63bd3","errorCode":null,"errorMessage":"{label} length {len(value)} does not match ids length {n}","messagePattern":"(.+?) length (.+?) does not match ids length (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/pgvector.py","lineNumber":1005,"sourceCode":"                \"embedding\": vector,\n                \"updated_at\": _utcnow(),\n            }\n            for doc_id, doc, meta, vector in zip(ids, documents, metadatas, vectors)\n        ]\n        self._client.upsert_rows(self._table, rows)\n        self._backend._write_marker(self._palace, self._config)\n\n    def update(self, *, ids, documents=None, metadatas=None, embeddings=None):\n        if documents is None and metadatas is None and embeddings is None:\n            raise ValueError(\"update requires at least one of documents, metadatas, embeddings\")\n        n = len(ids)\n        for label, value in (\n            (\"documents\", documents),\n            (\"metadatas\", metadatas),\n            (\"embeddings\", embeddings),\n        ):\n            if value is not None and len(value) != n:\n                raise ValueError(f\"{label} length {len(value)} does not match ids length {n}\")\n        existing = self.get(ids=ids, include=[\"documents\", \"metadatas\", \"embeddings\"])\n        by_id = {\n            rid: (existing.documents[i], existing.metadatas[i], existing.embeddings[i])\n            for i, rid in enumerate(existing.ids)\n            if existing.embeddings is not None\n        }\n        out_ids, out_docs, out_metas, out_embeddings = [], [], [], []\n        for idx, doc_id in enumerate(ids):\n            if doc_id not in by_id:\n                continue\n            prev_doc, prev_meta, prev_embedding = by_id[doc_id]\n            out_ids.append(doc_id)\n            out_docs.append(documents[idx] if documents is not None else prev_doc)\n            meta = dict(prev_meta or {})\n            if metadatas is not None:\n                meta.update(metadatas[idx] or {})\n            out_metas.append(meta)\n            out_embeddings.append(embeddings[idx] if embeddings is not None else prev_embedding)","sourceCodeStart":987,"sourceCodeEnd":1023,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/pgvector.py#L987-L1023","documentation":"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.","triggerScenarios":"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).","commonSituations":"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().","solutions":["Make all arrays the same length before calling update(), e.g. assert len(ids) == len(documents or ids) == len(metadatas or ids).","Build the batch as a single list of records ({id, document, metadata, embedding}) and derive the parallel arrays with zip(*(...)) so they cannot diverge.","Pass None for arrays you are not updating instead of an empty or stale list."],"exampleFix":"# before\ncollection.update(ids=ids, documents=new_docs, metadatas=metas)  # len mismatch\n\n# after\nassert len(ids) == len(new_docs) == len(metas)\ncollection.update(ids=ids, documents=new_docs, metadatas=metas)","handlingStrategy":"validation","validationCode":"def safe_update(col, ids, documents=None, metadatas=None, embeddings=None):\n    n = len(ids)\n    for name, arr in ((\"documents\", documents), (\"metadatas\", metadatas), (\"embeddings\", embeddings)):\n        if arr is not None and len(arr) != n:\n            raise ValueError(f\"{name} length {len(arr)} != ids length {n}\")\n    return col.update(ids=ids, documents=documents, metadatas=metadatas, embeddings=embeddings)","typeGuard":"def is_aligned_batch(ids, **arrays) -> bool:\n    return all(v is None or len(v) == len(ids) for v in arrays.values())","tryCatchPattern":"try:\n    col.update(ids=ids, documents=docs, metadatas=metas)\nexcept ValueError as e:\n    if \"does not match ids length\" in str(e):\n        logger.error(\"batch misaligned\", len_ids=len(ids))\n        raise","preventionTips":["Derive ids/documents/metadatas/embeddings from a single list of records so they cannot diverge.","Add an assert of equal lengths at the top of every ingest function.","Pass None instead of empty lists for arrays you are not updating."],"tags":["pgvector","validation","batch-mismatch","valueerror"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}