{"record":{"id":"acc44e351a44b943","repo":"BerriAI/litellm","slug":"ocr-response-usage-info-is-none","errorCode":null,"errorMessage":"OCR response usage_info is None","messagePattern":"OCR response usage_info is None","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/cost_calculator.py","lineNumber":1822,"sourceCode":"        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:\n        ocr_cost_per_page = model_info.get(\"ocr_cost_per_page\")\n\n    pages_processed: Final = response.usage_info.pages_processed","sourceCodeStart":1804,"sourceCodeEnd":1840,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/cost_calculator.py#L1804-L1840","documentation":"OCRResponse carries pricing data in its usage_info field. If the response passed to the OCR cost calculator has usage_info=None (provider returned no usage, or the transformation didn't populate it), LiteLLM refuses to compute cost and raises ValueError since pages/credits are unknown.","triggerScenarios":"Constructing OCRResponse without usage_info; an OCR provider call whose response lacks usage metadata; a transformation that maps usage fields only conditionally.","commonSituations":"Custom OCR integrations that skip usage mapping; providers that don't report pages processed; partially-implemented OCR transformations after upgrading LiteLLM.","solutions":["Populate usage_info when building OCRResponse (pages_processed and/or credits).","Fix the provider transformation to map the provider's usage fields into OCRUsageInfo.","Retry/bill externally when the provider genuinely returns no usage data rather than forcing cost calc.","Update LiteLLM for transformation fixes if the provider does return usage."],"exampleFix":"# before\nocr = OCRResponse(id=..., text=...)  # usage_info omitted -> None\n\n# after\nfrom litellm.llms.base_llm.ocr.transformation import OCRUsageInfo\nocr = OCRResponse(id=..., text=..., usage_info=OCRUsageInfo(pages_processed=2))","handlingStrategy":"type-guard","validationCode":"if response.usage_info is None:\n    raise ValueError(\"OCR response missing usage_info; cannot price\")","typeGuard":"def ocr_usage_present(resp) -> bool:\n    return isinstance(resp, OCRResponse) and resp.usage_info is not None","tryCatchPattern":"try:\n    cost = ocr_cost_fn(response=resp, model=model)\nexcept ValueError as e:\n    if \"usage_info is None\" in str(e):\n        cost = 0.0  # bill externally; log the gap\n    else:\n        raise","preventionTips":["Always populate OCRUsageInfo in transformations, even with partial data.","Log raw provider responses when usage is absent to identify schema changes.","Add contract tests asserting usage_info is set after transformation."],"tags":["litellm","cost-calculation","ocr","usage"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}