{"record":{"id":"13c07df43a4ba422","repo":"langchain-ai/langchain","slug":"search-type-of-self-search-type-not-allowed","errorCode":null,"errorMessage":"search_type of {self.search_type} not allowed.","messagePattern":"search_type of (.+?) not allowed\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/vectorstores/base.py","lineNumber":1057,"sourceCode":"    @override\n    def _get_relevant_documents(\n        self, query: str, *, run_manager: CallbackManagerForRetrieverRun, **kwargs: Any\n    ) -> list[Document]:\n        kwargs_ = self.search_kwargs | kwargs\n        if self.search_type == \"similarity\":\n            docs = self.vectorstore.similarity_search(query, **kwargs_)\n        elif self.search_type == \"similarity_score_threshold\":\n            docs_and_similarities = (\n                self.vectorstore.similarity_search_with_relevance_scores(\n                    query, **kwargs_\n                )\n            )\n            docs = [doc for doc, _ in docs_and_similarities]\n        elif self.search_type == \"mmr\":\n            docs = self.vectorstore.max_marginal_relevance_search(query, **kwargs_)\n        else:\n            msg = f\"search_type of {self.search_type} not allowed.\"\n            raise ValueError(msg)\n        return docs\n\n    @override\n    async def _aget_relevant_documents(\n        self,\n        query: str,\n        *,\n        run_manager: AsyncCallbackManagerForRetrieverRun,\n        **kwargs: Any,\n    ) -> list[Document]:\n        kwargs_ = self.search_kwargs | kwargs\n        if self.search_type == \"similarity\":\n            docs = await self.vectorstore.asimilarity_search(query, **kwargs_)\n        elif self.search_type == \"similarity_score_threshold\":\n            docs_and_similarities = (\n                await self.vectorstore.asimilarity_search_with_relevance_scores(\n                    query, **kwargs_\n                )","sourceCodeStart":1039,"sourceCodeEnd":1075,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/vectorstores/base.py#L1039-L1075","documentation":"Defensive dispatch inside `VectorStoreRetriever._get_relevant_documents`: after checking the three known `search_type` values, an unrecognized value falls into the `else` branch and raises `ValueError`. Normally unreachable because the Pydantic validator rejects bad values at construction, but it catches subclasses that loosen validation, mutate `search_type` after construction, or construct the model bypassing validators (`model_construct`).","triggerScenarios":"Mutating `retriever.search_type = 'custom'` after creation; a subclass overriding the validator or `allowed_search_types` without handling the new value in `_get_relevant_documents`; building the retriever via `model_construct` (no validation) with an invalid type.","commonSituations":"Dynamic config applied by assigning attributes post-init; custom retriever subclasses adding search modes that pass validation but skip dispatch handling; deserialization paths that skip Pydantic validation.","solutions":["Set `search_type` at construction time to a validator-approved value instead of mutating it afterwards.","If you subclass and extend `allowed_search_types`, also override `_get_relevant_documents` (and `_aget_relevant_documents`) to handle the new values.","Re-validate after mutation: `retriever = VectorStoreRetriever.model_validate(retriever.model_dump())`."],"exampleFix":"# before\nretriever = store.as_retriever()\nretriever.search_type = \"hybrid\"  # passes attribute set, fails at query time\n\ndocs = retriever.invoke(\"query\")  # ValueError: search_type of hybrid not allowed\n\n# after\nclass HybridRetriever(VectorStoreRetriever):\n    allowed_search_types = VectorStoreRetriever.allowed_search_types | {\"hybrid\"}\n\n    def _get_relevant_documents(self, query, *, run_manager, **kwargs):\n        if self.search_type == \"hybrid\":\n            return self._hybrid_search(query, **kwargs)\n        return super()._get_relevant_documents(query, run_manager=run_manager, **kwargs)","handlingStrategy":"validation","validationCode":"from langchain_core.vectorstores import VectorStoreRetriever\n\ndef set_search_type(retriever, search_type: str):\n    \"\"\"Safely change search_type by re-validating instead of mutating.\"\"\"\n    if search_type not in retriever.allowed_search_types:\n        raise ValueError(f\"{search_type!r} not in {retriever.allowed_search_types}\")\n    return retriever.model_copy(update={\"search_type\": search_type})","typeGuard":"def retriever_search_type_is_valid(retriever, value: str) -> bool:\n    \"\"\"Narrow before dispatch; guards post-construction mutation.\"\"\"\n    return value in type(retriever).allowed_search_types","tryCatchPattern":"try:\n    docs = retriever.invoke(query)\nexcept ValueError as e:\n    if \"search_type\" in str(e):\n        retriever = retriever.model_copy(update={\"search_type\": \"similarity\"})\n        docs = retriever.invoke(query)\n    else:\n        raise","preventionTips":["Never assign `retriever.search_type` directly; rebuild via `as_retriever(...)` or `model_copy(update=...)`.","Subclasses adding search types must update `allowed_search_types` AND both dispatch methods.","Add a regression test that constructs your retriever config through normal validation (not `model_construct`)."],"tags":["retriever","dispatch","subclassing"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}