BerriAI/litellm · error · NotImplementedError
transform_search_response must be implemented by provider
Error message
transform_search_response must be implemented by provider
What it means
BaseSearchConfig.transform_search_response() converts the provider's raw httpx.Response into LiteLLM's normalized SearchResponse. It is an abstract stub raising NotImplementedError. Encountering it means a search request succeeded at the HTTP layer but the active config never implemented response parsing (base class or incomplete custom provider), so results cannot be normalized.
Source
Thrown at litellm/llms/base_llm/search/transformation.py:242
query: Search query (string or list of strings)
optional_params: Optional parameters for the request
Returns:
Dict with request data
"""
raise NotImplementedError("transform_search_request must be implemented by provider")
def transform_search_response(
self,
raw_response: httpx.Response,
logging_obj: LiteLLMLoggingObj,
**kwargs,
) -> SearchResponse:
"""
Transform provider-specific Search response to standard format.
Override in provider-specific implementations.
"""
raise NotImplementedError("transform_search_response must be implemented by provider")
def get_error_class(
self,
error_message: str,
status_code: int,
headers: dict,
) -> Exception:
"""Get appropriate error class for the provider."""
return BaseLLMException(
status_code=status_code,
message=error_message,
headers=headers,
)
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Implement `def transform_search_response(self, raw_response, logging_obj, **kwargs) -> SearchResponse` mapping provider JSON (results, titles, urls, snippets) into SearchResponse.
- Or use a built-in provider whose transformation is complete.
- Mirror the structure of an existing implementation (e.g. litellm/llms/gemini or exa search transformation) to satisfy the SearchResponse contract.
Example fix
# before
class MySearch(BaseSearchConfig):
... # no transform_search_response -> NotImplementedError on 2xx
# after
from litellm.types.llms.openai import SearchResponse, SearchResponseResult
class MySearch(BaseSearchConfig):
def transform_search_response(self, raw_response, logging_obj, **kwargs) -> SearchResponse:
data = raw_response.json()
return SearchResponse(results=[
SearchResponseResult(title=r["title"], url=r["link"], snippet=r["snippet"])
for r in data["items"]
]) Defensive patterns
Strategy: type-guard
Validate before calling
from litellm.llms.base_llm.search.transformation import BaseSearchConfig assert type(cfg).transform_search_response is not BaseSearchConfig.transform_search_response
Type guard
from litellm.llms.base_llm.search.transformation import BaseSearchConfig
def supports_search_response_transform(cfg: BaseSearchConfig) -> bool:
return type(cfg).transform_search_response is not BaseSearchConfig.transform_search_response Prevention
- Keep a recorded 2xx response fixture per provider and test the mapper against it.
- Check SearchResponse schema on litellm upgrades; response shape changes surface here.
When it happens
Trigger: A provider returns 2xx from the search endpoint, then litellm calls transform_search_response on a config lacking the override — custom providers, or fallback-to-base routing.
Common situations: Custom search provider implementations that built and sent the request but never wrote the response mapper; schema drift after a litellm upgrade changed SearchResponse expectations.
Related errors
- get_complete_url must be implemented by provider
- transform_search_request must be implemented by provider
- validate_environment must be implemented by provider
- acreate_sandbox must be implemented by provider
- arun_code must be implemented by provider
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/5320e9a20f67fa00.
Report an issue: GitHub.