langchain-ai/langchain · error · ValueError

search_type of {self.search_type} not allowed.

Error message

search_type of {self.search_type} not allowed.

What it means

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`).

Source

Thrown at libs/core/langchain_core/vectorstores/base.py:1057

    @override
    def _get_relevant_documents(
        self, query: str, *, run_manager: CallbackManagerForRetrieverRun, **kwargs: Any
    ) -> list[Document]:
        kwargs_ = self.search_kwargs | kwargs
        if self.search_type == "similarity":
            docs = self.vectorstore.similarity_search(query, **kwargs_)
        elif self.search_type == "similarity_score_threshold":
            docs_and_similarities = (
                self.vectorstore.similarity_search_with_relevance_scores(
                    query, **kwargs_
                )
            )
            docs = [doc for doc, _ in docs_and_similarities]
        elif self.search_type == "mmr":
            docs = self.vectorstore.max_marginal_relevance_search(query, **kwargs_)
        else:
            msg = f"search_type of {self.search_type} not allowed."
            raise ValueError(msg)
        return docs

    @override
    async def _aget_relevant_documents(
        self,
        query: str,
        *,
        run_manager: AsyncCallbackManagerForRetrieverRun,
        **kwargs: Any,
    ) -> list[Document]:
        kwargs_ = self.search_kwargs | kwargs
        if self.search_type == "similarity":
            docs = await self.vectorstore.asimilarity_search(query, **kwargs_)
        elif self.search_type == "similarity_score_threshold":
            docs_and_similarities = (
                await self.vectorstore.asimilarity_search_with_relevance_scores(
                    query, **kwargs_
                )

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Set `search_type` at construction time to a validator-approved value instead of mutating it afterwards.
  2. If you subclass and extend `allowed_search_types`, also override `_get_relevant_documents` (and `_aget_relevant_documents`) to handle the new values.
  3. Re-validate after mutation: `retriever = VectorStoreRetriever.model_validate(retriever.model_dump())`.

Example fix

# before
retriever = store.as_retriever()
retriever.search_type = "hybrid"  # passes attribute set, fails at query time

docs = retriever.invoke("query")  # ValueError: search_type of hybrid not allowed

# after
class HybridRetriever(VectorStoreRetriever):
    allowed_search_types = VectorStoreRetriever.allowed_search_types | {"hybrid"}

    def _get_relevant_documents(self, query, *, run_manager, **kwargs):
        if self.search_type == "hybrid":
            return self._hybrid_search(query, **kwargs)
        return super()._get_relevant_documents(query, run_manager=run_manager, **kwargs)
Defensive patterns

Strategy: validation

Validate before calling

from langchain_core.vectorstores import VectorStoreRetriever

def set_search_type(retriever, search_type: str):
    """Safely change search_type by re-validating instead of mutating."""
    if search_type not in retriever.allowed_search_types:
        raise ValueError(f"{search_type!r} not in {retriever.allowed_search_types}")
    return retriever.model_copy(update={"search_type": search_type})

Type guard

def retriever_search_type_is_valid(retriever, value: str) -> bool:
    """Narrow before dispatch; guards post-construction mutation."""
    return value in type(retriever).allowed_search_types

Try / catch

try:
    docs = retriever.invoke(query)
except ValueError as e:
    if "search_type" in str(e):
        retriever = retriever.model_copy(update={"search_type": "similarity"})
        docs = retriever.invoke(query)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/13c07df43a4ba422. Report an issue: GitHub.