{"record":{"id":"03aeacf9d7eeef82","repo":"langchain-ai/langchain","slug":"vectorstore-should-be-either-a-vectorstore-or-a-do-03aeac","errorCode":null,"errorMessage":"Vectorstore should be either a VectorStore or a DocumentIndex. Got {type(destination)}.","messagePattern":"Vectorstore should be either a VectorStore or a DocumentIndex\\. Got (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/indexing/api.py","lineNumber":450,"sourceCode":"            if not hasattr(destination, method):\n                msg = (\n                    f\"Vectorstore {destination} does not have required method {method}\"\n                )\n                raise ValueError(msg)\n\n        if type(destination).delete == VectorStore.delete:\n            # Checking if the VectorStore has overridden the default delete method\n            # implementation which just raises a NotImplementedError\n            msg = \"Vectorstore has not implemented the delete method\"\n            raise ValueError(msg)\n    elif isinstance(destination, DocumentIndex):\n        pass\n    else:\n        msg = (  # type: ignore[unreachable]\n            f\"Vectorstore should be either a VectorStore or a DocumentIndex. \"\n            f\"Got {type(destination)}.\"\n        )\n        raise TypeError(msg)\n\n    if isinstance(docs_source, BaseLoader):\n        try:\n            doc_iterator = docs_source.lazy_load()\n        except NotImplementedError:\n            doc_iterator = iter(docs_source.load())\n    else:\n        doc_iterator = iter(docs_source)\n\n    source_id_assigner = _get_source_id_assigner(source_id_key)\n\n    # Mark when the update started.\n    index_start_dt = record_manager.get_time()\n    num_added = 0\n    num_skipped = 0\n    num_updated = 0\n    num_deleted = 0\n    scoped_full_cleanup_source_ids: set[str] = set()","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/indexing/api.py#L432-L468","documentation":"Raised in `index()` when the destination object is neither a `VectorStore` nor a `DocumentIndex`. The indexer must upsert and delete documents through one of those two protocols; passing a retriever, a bare client, a string DSN, or a duck-typed object that never subclasses the right base class results in a `TypeError`. The type annotation makes this unreachable for typed callers, but dynamic code bypasses it.","triggerScenarios":"Calling `index(my_retriever, docs, rm)`; passing `vectorstore.as_retriever()` output; passing the underlying client (e.g. a `chromadb.Collection`) instead of the LangChain wrapper; test mocks without proper subclassing.","commonSituations":"Confusing retrievers with stores; grabbing low-level SDK clients from LangChain integrations (`store._collection`); refactors that swap the store for a facade object.","solutions":["Pass the LangChain `VectorStore` wrapper object itself (e.g. the `Chroma` instance, not its `_collection`).","Make custom destinations subclass `VectorStore` or implement `DocumentIndex`.","If given a retriever, recover the store via its `vectorstore` attribute where available."],"exampleFix":"# before\nindex(chroma._collection, docs, rm, cleanup=\"full\")\n\n# after\nindex(chroma, docs, rm, cleanup=\"full\")","handlingStrategy":"type-guard","validationCode":"from langchain_core.vectorstores import VectorStore\n\nassert isinstance(destination, VectorStore), (\n    f\"expected VectorStore, got {type(destination).__name__}; \"\n    \"pass the LangChain wrapper, not a retriever or raw client\"\n)\nindex(destination, docs, rm, cleanup=\"full\")","typeGuard":"def is_indexing_destination(obj) -> bool:\n    from langchain_core.vectorstores import VectorStore\n    from langchain_core.indexing.api import DocumentIndex\n    return isinstance(obj, (VectorStore, DocumentIndex))","tryCatchPattern":null,"preventionTips":["Never unwrap stores (`._collection`, `.client`) before calling index().","Annotate parameters as VectorStore and run mypy to catch duck-typed misuse."],"tags":["indexing","type-error","vector-store","document-index"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}