BerriAI/litellm · error · NotImplementedError

transform_ocr_request must be implemented by provider

Error message

transform_ocr_request must be implemented by provider

What it means

Base OCR transformation stub for transform_ocr_request: converting the unified document input (document_url / image_url dict produced by litellm/ocr/main.py preprocessing) into a provider payload is provider-specific, so the base class raises NotImplementedError. A config without this override cannot serve OCR requests.

Source

Thrown at litellm/llms/base_llm/ocr/transformation.py:176

    ) -> OCRRequestData:
        """
        Transform OCR request to provider-specific format.
        Override in provider-specific implementations.

        Note: By the time this method is called, any file-type documents have already
        been converted to document_url/image_url format with base64 data URIs by
        the preprocessing in litellm/ocr/main.py.

        Args:
            model: Model name
            document: Document to process - always a dict with type="document_url" or type="image_url"
            optional_params: Optional parameters for the request
            headers: Request headers

        Returns:
            OCRRequestData with data and files fields
        """
        raise NotImplementedError("transform_ocr_request must be implemented by provider")

    async def async_transform_ocr_request(
        self,
        model: str,
        document: DocumentType,
        optional_params: dict,
        headers: dict,
        **kwargs,
    ) -> OCRRequestData:
        """
        Async transform OCR request to provider-specific format.
        Optional method - providers can override if they need async transformations
        (e.g., Azure AI for URL-to-base64 conversion).

        Default implementation falls back to sync transform_ocr_request.

        Args:
            model: Model name

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Implement transform_ocr_request in the provider config returning OCRRequestData(data=..., files=...).
  2. Confirm the provider string in the model name resolves to a concrete OCR config (check the provider registry).
  3. Switch to a supported OCR provider until the custom one is complete.
  4. Update litellm if support for the provider exists upstream.

Example fix

# before
class MyOCRConfig(BaseOCRConfig): ...
# NotImplementedError at request transform

# after
class MyOCRConfig(BaseOCRConfig):
    def transform_ocr_request(self, model, document, optional_params, headers, **kwargs):
        return OCRRequestData(data={'url': document['document_url']['url'], 'model': model}, files=None)
Defensive patterns

Strategy: type-guard

Type guard

def can_transform_ocr_request(config) -> bool:
    return type(config).transform_ocr_request is not BaseOCRConfig.transform_ocr_request

Try / catch

try:
    req = config.transform_ocr_request(model, document, optional_params, headers)
except NotImplementedError:
    raise ConfigError('provider config incomplete: transform_ocr_request missing') from None

Prevention

When it happens

Trigger: litellm.ocr() invoked with a provider config lacking transform_ocr_request; partially implemented custom OCR integration; provider resolution falling through to the base config (unknown custom_llm_provider).

Common situations: Contributing a new OCR provider and forgetting the request transform; model strings like 'ocr/my-provider' not matching any registered config; running an older litellm against docs for a newer provider integration.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/1189fa211e04eb71. Report an issue: GitHub.