{"record":{"id":"de02ad7e2b6c50d8","repo":"BerriAI/litellm","slug":"response-must-be-of-type-ocrresponse-got-type-typ","errorCode":null,"errorMessage":"response must be of type OCRResponse got type={type(response)}","messagePattern":"response must be of type OCRResponse got type=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/cost_calculator.py","lineNumber":1819,"sourceCode":") -> tuple[float, float]:\n    \"\"\"\n    Args:\n        model: str - model name\n        custom_llm_provider: Optional[str] - custom LLM provider\n        response: Optional[Any] - response object\n\n    Returns:\n        Tuple[float, float]: cost of OCR processing\n\n        (Parent function requires a tuple, so we return a tuple. Cost is only in the first element.)\n    \"\"\"\n    from litellm.llms.base_llm.ocr.transformation import OCRResponse\n\n    #########################################################\n    # validate it's an OCR response\n    #########################################################\n    if response is None or not isinstance(response, OCRResponse):\n        raise ValueError(f\"response must be of type OCRResponse got type={type(response)}\")\n\n    if response.usage_info is None:\n        raise ValueError(\"OCR response usage_info is None\")\n\n    try:\n        model_info: ModelInfo | None = litellm.get_model_info(model=model, custom_llm_provider=custom_llm_provider)\n    except Exception:\n        model_info = None\n\n    credits: Final = getattr(response.usage_info, \"credits\", None)\n    cost_per_credit = None\n    if model_info is not None:\n        cost_per_credit = model_info.get(\"ocr_cost_per_credit\")\n    if credits is not None and cost_per_credit is not None:\n        return cost_per_credit * credits, 0.0\n\n    ocr_cost_per_page: float | None = None\n    if model_info is not None:","sourceCodeStart":1801,"sourceCodeEnd":1837,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/cost_calculator.py#L1801-L1837","documentation":"The OCR cost calculator only prices OCRResponse objects (litellm.llms.base_llm.ocr.transformation.OCRResponse). If response is None or any other type — e.g. a raw provider dict or a generic ModelResponse — it raises ValueError reporting the actual type.","triggerScenarios":"Calling the OCR cost path (ocr cost calculation invoked via cost_calculator for call_type OCR) with a plain dict, a provider-native response, or None instead of an OCRResponse instance.","commonSituations":"Custom OCR handlers returning raw JSON; version drift where the expected return type changed to OCRResponse; passing the unwrapped HTTP body instead of the transformed response.","solutions":["Return/transform to OCRResponse in your OCR handler (subclass the base transformation so LiteLLM yields OCRResponse).","If you have raw data, construct OCRResponse(...) (with usage_info) before computing cost.","Update LiteLLM so your provider's OCR transformation matches the current base interface.","Skip LiteLLM cost calc for non-conforming responses and price manually."],"exampleFix":"# before\nresp = await client.post(...)  # raw dict\ncost = litellm.cost_calculator.ocr_cost_calculator(response=resp.json(), model=...)\n\n# after\nfrom litellm.llms.base_llm.ocr.transformation import OCRResponse, OCRUsageInfo\nocr = OCRResponse(..., usage_info=OCRUsageInfo(pages_processed=3, credits=None))\ncost = litellm.cost_calculator.ocr_cost_calculator(response=ocr, model=...)","handlingStrategy":"type-guard","validationCode":"from litellm.llms.base_llm.ocr.transformation import OCRResponse\nif not isinstance(response, OCRResponse):\n    raise TypeError(f\"expected OCRResponse, got {type(response).__name__}\")","typeGuard":"from litellm.llms.base_llm.ocr.transformation import OCRResponse\n\ndef is_ocr_response(resp) -> bool:\n    return isinstance(resp, OCRResponse)","tryCatchPattern":"try:\n    cost = ocr_cost_fn(response=response, model=model)\nexcept ValueError as e:\n    if \"must be of type OCRResponse\" in str(e):\n        raise TypeError(f\"handler returned {type(response).__name__}; fix transformation\") from e\n    raise","preventionTips":["OCR handlers must transform provider payloads into OCRResponse objects.","Never pass raw dicts or provider SDK objects to cost calculators.","Type-check responses at your handler boundary."],"tags":["litellm","cost-calculation","ocr","type-validation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}