{"record":{"id":"8a2ce5bfc09c8bd0","repo":"MemPalace/mempalace","slug":"documents-length-len-documents-does-not-match-i-8a2ce5","errorCode":null,"errorMessage":"documents length {len(documents)} does not match ids length {n}","messagePattern":"documents length (.+?) does not match ids length (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/sqlite_exact.py","lineNumber":244,"sourceCode":"            continue\n        if key == \"$or\":\n            if not any(_matches_where_document(document, clause) for clause in value or []):\n                return False\n            continue\n        raise UnsupportedFilterError(f\"where_document operator {key!r} not supported\")\n    return True\n\n\ndef _validate_write_batch(\n    *,\n    documents: list[str],\n    ids: list[str],\n    metadatas: Optional[list[dict]],\n    embeddings: Optional[list[list[float]]],\n) -> None:\n    n = len(ids)\n    if len(documents) != n:\n        raise ValueError(f\"documents length {len(documents)} does not match ids length {n}\")\n    if metadatas is not None and len(metadatas) != n:\n        raise ValueError(f\"metadatas length {len(metadatas)} does not match ids length {n}\")\n    if embeddings is not None and len(embeddings) != n:\n        raise ValueError(f\"embeddings length {len(embeddings)} does not match ids length {n}\")\n\n\nclass _SQLiteExactHandle:\n    def __init__(\n        self,\n        conn: sqlite3.Connection,\n        lock: threading.RLock,\n        palace_path: str,\n        *,\n        read_only: bool = False,\n        immutable: bool = False,\n    ):\n        self.conn = conn\n        self.lock = lock","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/sqlite_exact.py#L226-L262","documentation":"Raised by sqlite_exact's `_validate_write_batch` before any SQL runs: the `documents` list has a different length than the `ids` list. The backend requires all parallel arrays in a batch write (upsert/add) to align element-for-element, so a length mismatch is rejected atomically instead of producing partially-paired rows.","triggerScenarios":"Calling `upsert(ids=[...], documents=[...], ...)` (or add) where `len(documents) != len(ids)` — e.g. building documents with a comprehension that filters items while ids come from the unfiltered source, or appending to one list inside a conditional branch.","commonSituations":"Batch construction loops that skip empty documents but keep the id; off-by-one slicing (`ids[1:]` but `documents`); refactoring a single-item write to a batch and forgetting to wrap one argument in a list.","solutions":["Assert `len(documents) == len(ids)` right before the write call and log both lengths.","Build documents and ids in the same loop iteration so they cannot diverge.","Zip your source records once (`for id, doc in zip(ids, documents)`) and derive both lists from the zipped pairs.","Fix the construction bug: usually a filter/`if` applied to only one of the two lists."],"exampleFix":"# before\nids = [r[\"id\"] for r in records]\ndocuments = [r[\"text\"] for r in records if r[\"text\"].strip()]  # shorter!\ncol.upsert(ids=ids, documents=documents)\n\n# after\npairs = [(r[\"id\"], r[\"text\"]) for r in records if r[\"text\"].strip()]\ncol.upsert(ids=[p[0] for p in pairs], documents=[p[1] for p in pairs])","handlingStrategy":"validation","validationCode":"def validate_batch(ids, documents, metadatas=None, embeddings=None):\n    n = len(ids)\n    assert len(documents) == n, f\"documents {len(documents)} != ids {n}\"\n    if metadatas is not None:\n        assert len(metadatas) == n\n    if embeddings is not None:\n        assert len(embeddings) == n\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    col.upsert(ids=ids, documents=documents, embeddings=embeddings)\nexcept ValueError as e:\n    if \"does not match ids length\" in str(e):\n        logger.error(\"batch misaligned: ids=%d docs=%d emb=%d\", len(ids), len(documents), len(embeddings or []))\n        raise","preventionTips":["Build ids, documents, metadatas, embeddings in one loop over the same source records.","Add a pre-upsert assert of all list lengths in dev/test builds.","Never filter one list independently of its siblings."],"tags":["sqlite-exact","batch-write","validation","upsert"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}