{"record":{"id":"6ea6495488c57b08","repo":"BerriAI/litellm","slug":"completion-response-must-be-of-type-imageresponse","errorCode":null,"errorMessage":"completion_response must be of type ImageResponse for bedrock image cost calculation","messagePattern":"completion_response must be of type ImageResponse for bedrock image cost calculation","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/llm_cost_calc/utils.py","lineNumber":1198,"sourceCode":"            quality = completion_response.quality or \"standard\"\n        if n is None:\n            n = len(completion_response.data) if completion_response.data else 0\n\n        if custom_llm_provider == litellm.LlmProviders.VERTEX_AI.value:\n            if isinstance(completion_response, ImageResponse):\n                return vertex_ai_image_cost_calculator(\n                    model=model,\n                    image_response=completion_response,\n                )\n        elif custom_llm_provider == litellm.LlmProviders.BEDROCK.value:\n            if isinstance(completion_response, ImageResponse):\n                return bedrock_image_cost_calculator(\n                    model=model,\n                    size=size,\n                    image_response=completion_response,\n                    optional_params=optional_params,\n                )\n            raise TypeError(\"completion_response must be of type ImageResponse for bedrock image cost calculation\")\n        elif custom_llm_provider == litellm.LlmProviders.RECRAFT.value:\n            from litellm.llms.recraft.cost_calculator import (\n                cost_calculator as recraft_image_cost_calculator,\n            )\n\n            return recraft_image_cost_calculator(\n                model=model,\n                image_response=completion_response,\n            )\n        elif custom_llm_provider == litellm.LlmProviders.AIML.value:\n            from litellm.llms.aiml.image_generation.cost_calculator import (\n                cost_calculator as aiml_image_cost_calculator,\n            )\n\n            return aiml_image_cost_calculator(\n                model=model,\n                image_response=completion_response,\n            )","sourceCodeStart":1180,"sourceCodeEnd":1216,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/llm_cost_calc/utils.py#L1180-L1216","documentation":"Raised by litellm's generic cost-calculator dispatch when a Bedrock image-generation cost is requested but the completion_response argument is not an instance of litellm.types.utils.ImageResponse. The dispatcher (used by response_cost calculation and proxy spend tracking) branches per provider; only ImageResponse objects carry the Bedrock image metadata needed for pricing. Passing a ModelResponse, a raw dict, or None triggers this TypeError before any pricing math runs.","triggerScenarios":"Calling litellm.completion_cost() / cost calculation internals with custom_llm_provider='bedrock' and response_type='image_generation' where completion_response is not an ImageResponse; building custom image-generation handler code that returns a dict or ModelResponse instead of ImageResponse; calling bedrock_image_cost_calculator via the generic dispatcher with a mocked/wrong-type response object.","commonSituations":"Custom providers or wrappers that intercept image generation and forward a plain dict to cost tracking; unit tests that mock cost calculation with fake objects; version upgrades where the image cost API was tightened to require ImageResponse (previously accepted dicts silently).","solutions":["Ensure the value passed as completion_response for bedrock image calls is a litellm.types.utils.ImageResponse (e.g. built via LiteLLMResponseObjectHandler.convert_to_image_response).","If you call the dispatcher directly, branch on isinstance(completion_response, ImageResponse) before selecting the bedrock image path, mirroring utils.py:1196.","In custom handler code, convert raw provider JSON into ImageResponse before returning it so downstream cost tracking sees the right type.","If you never intend image pricing, route the call through the standard completion/embedding cost calculators instead of the image-generation branch."],"exampleFix":"// before\nresp = await client.images.generate(...)  # raw dict kept\ncost = litellm.completion_cost(completion_response=resp, model='bedrock/titan-image')\n\n# after\nfrom litellm.types.utils import ImageResponse\nimg = ImageResponse(**resp)  # or convert_to_image_response(...)\ncost = litellm.completion_cost(completion_response=img, model='bedrock/titan-image')","handlingStrategy":"type-guard","validationCode":"from litellm.types.utils import ImageResponse\ndef is_image_response(resp) -> bool:\n    return isinstance(resp, ImageResponse)","typeGuard":"from litellm.types.utils import ImageResponse\nfrom typing import TypeGuard\n\ndef is_image_response(resp: object) -> TypeGuard[ImageResponse]:\n    return isinstance(resp, ImageResponse)","tryCatchPattern":"try:\n    cost = litellm.completion_cost(completion_response=resp, model=model)\nexcept TypeError as e:\n    if 'ImageResponse' in str(e):\n        resp = ImageResponse(**resp) if isinstance(resp, dict) else resp\n        cost = litellm.completion_cost(completion_response=resp, model=model)\n    else:\n        raise","preventionTips":["Always construct ImageResponse via litellm's converters rather than passing raw dicts into cost APIs.","In custom handlers, type-annotate the return value as ImageResponse so mypy catches mismatches.","Add isinstance assertions in tests covering cost calculation paths."],"tags":["bedrock","image-generation","cost-calculation","type-error"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}