{"record":{"id":"0d9f1faa1ff9bceb","repo":"langchain-ai/langchain","slug":"ids-must-be-the-same-length-as-texts-got-len-ids","errorCode":null,"errorMessage":"ids must be the same length as texts. Got {len(ids)} ids and {len(texts)} texts.","messagePattern":"ids must be the same length as texts\\. Got (.+?) ids and (.+?) texts\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/vectorstores/in_memory.py","lineNumber":202,"sourceCode":"    async def adelete(self, ids: Sequence[str] | None = None, **kwargs: Any) -> None:\n        self.delete(ids)\n\n    @override\n    def add_documents(\n        self,\n        documents: list[Document],\n        ids: list[str] | None = None,\n        **kwargs: Any,\n    ) -> list[str]:\n        texts = [doc.page_content for doc in documents]\n        vectors = self.embedding.embed_documents(texts)\n\n        if ids and len(ids) != len(texts):\n            msg = (\n                f\"ids must be the same length as texts. \"\n                f\"Got {len(ids)} ids and {len(texts)} texts.\"\n            )\n            raise ValueError(msg)\n\n        id_iterator: Iterator[str | None] = (\n            iter(ids) if ids else iter(doc.id for doc in documents)\n        )\n\n        ids_ = []\n\n        for doc, vector in zip(documents, vectors, strict=False):\n            doc_id = next(id_iterator)\n            doc_id_ = doc_id or str(uuid.uuid4())\n            ids_.append(doc_id_)\n            self.store[doc_id_] = {\n                \"id\": doc_id_,\n                \"vector\": vector,\n                \"text\": doc.page_content,\n                \"metadata\": doc.metadata,\n            }\n","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/vectorstores/in_memory.py#L184-L220","documentation":"Thrown by InMemoryVectorStore.add_documents when the optional ids list is supplied but its length does not match the number of documents being added. The store requires a one-to-one mapping between documents and ids so each vector can be keyed correctly in self.store. The check runs after embedding, so the embed_documents call still executes (and may cost an API call) before the ValueError is raised.","triggerScenarios":"Calling add_documents(documents, ids=[...]) where len(ids) != len(documents). Note the guard is `if ids and len(ids) != len(texts)`: passing an empty list ([]) is treated as falsy and falls back to document ids/uuids, so the error only fires for a non-empty ids list of the wrong length. Also reachable via add_texts-style wrappers or VectorStore.from_documents-style helpers that forward a mismatched ids argument.","commonSituations":"Appending new documents to an existing ids list but forgetting to extend it; batching documents into chunks (e.g. via chunking or parallel loops) while reusing the full-length ids list per batch; off-by-one when constructing ids with list comprehension ranges; refactoring from add_texts (where ids aligned with strings) to add_documents without resizing ids.","solutions":["Make ids match the batch exactly: build ids in the same comprehension/loop that builds documents, e.g. ids = [f'doc-{i}' for i in range(len(documents))].","If you want automatic id generation, pass ids=None (or omit it) so the store falls back to doc.id or a generated uuid4 per document.","Set an explicit id on each Document (Document(page_content=..., id=...)) instead of passing a separate ids list, keeping ids and documents coupled by construction.","Add an assertion before the call: assert ids is None or len(ids) == len(documents), to fail before the embedding step rather than after it."],"exampleFix":"// before\nids = [\"a\", \"b\", \"c\"]\nstore.add_documents(docs_of_length_5, ids=ids)  # ValueError\n\n// after\nids = [f\"doc-{i}\" for i in range(len(docs))]\nstore.add_documents(docs, ids=ids)","handlingStrategy":"validation","validationCode":"def validate_add_documents(documents: list, ids: list[str] | None) -> None:\n    if ids is not None and len(ids) != len(documents):\n        msg = f\"ids length {len(ids)} != documents length {len(documents)}\"\n        raise ValueError(msg)","typeGuard":"from typing import TypeGuard\nfrom langchain_core.documents import Document\n\ndef has_matching_ids(documents: list[Document], ids: object) -> TypeGuard[list[str]]:\n    return isinstance(ids, list) and len(ids) == len(documents) and all(isinstance(i, str) for i in ids)","tryCatchPattern":"try:\n    store.add_documents(documents, ids=ids)\nexcept ValueError as e:\n    if \"ids must be the same length as texts\" in str(e):\n        logger.error(\"ids/documents length mismatch: %s vs %s\", len(ids or []), len(documents))\n        ids = None  # fall back to doc.id / uuid generation\n        store.add_documents(documents, ids=ids)\n    else:\n        raise","preventionTips":["Derive ids from the documents collection itself (same comprehension) instead of maintaining a parallel list.","Prefer setting Document(id=...) over a separate ids argument so ids cannot drift from documents.","When batching, slice ids with the same slice bounds as documents: docs_batch, ids_batch = documents[i:i+n], ids[i:i+n].","Assert length equality before the call so you fail before paying for embeddings."],"tags":["validation","vectorstore","in-memory","ids","add-documents"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}