From 46b90612d545d289f5a7fc3127a9c267f922f446 Mon Sep 17 00:00:00 2001 From: Aishwary Dongre Date: Thu, 15 Oct 2026 10:31:32 +0530 Subject: [PATCH 1/2] fix(cost): pass data_residency and optional_params to gpt-image cost calculator OpenAI image generation (gpt-image-*) routed through EU regions (e.g., https://eu.api.openai.com/v1) should apply a 10% data residency uplift for models released after 2026-03-05, but the cost calculator was not receiving the data_residency parameter. Additionally, deployment-level custom prices like output_cost_per_image_token were being ignored because optional_params wasn't passed through. This passes both parameters from the router cost calculation to the gpt-image cost calculator, which forwards them to generic_cost_per_token and calculate_image_response_cost_from_usage. Fixes #46407 --- .../litellm_core_utils/llm_cost_calc/utils.py | 2 ++ .../image_generation/cost_calculator.py | 23 ++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/litellm/litellm_core_utils/llm_cost_calc/utils.py b/litellm/litellm_core_utils/llm_cost_calc/utils.py index 2afb6ed4c58..6709bf7a0a5 100644 --- a/litellm/litellm_core_utils/llm_cost_calc/utils.py +++ b/litellm/litellm_core_utils/llm_cost_calc/utils.py @@ -2104,6 +2104,8 @@ class CostCalculatorUtils: image_response=completion_response, custom_llm_provider=custom_llm_provider, model_info=pricing, + data_residency=data_residency, + optional_params=optional_params, ) # Fall through to default for DALL-E models return default_image_cost_calculator( diff --git a/litellm/llms/openai/image_generation/cost_calculator.py b/litellm/llms/openai/image_generation/cost_calculator.py index 350fdbaee2d..696d416b050 100644 --- a/litellm/llms/openai/image_generation/cost_calculator.py +++ b/litellm/llms/openai/image_generation/cost_calculator.py @@ -21,6 +21,8 @@ def cost_calculator( image_response: ImageResponse, custom_llm_provider: str | None = None, model_info: ModelInfo | None = None, + data_residency: str | None = None, + optional_params: dict | None = None, ) -> float: """Calculate cost for OpenAI gpt-image models (token-based pricing).""" provider: Final = custom_llm_provider or "openai" @@ -38,7 +40,12 @@ def cost_calculator( # A chat Usage with an explicit output breakdown: cost via generic_cost_per_token. if isinstance(usage, Usage) and usage.completion_tokens_details is not None: prompt_cost, completion_cost = generic_cost_per_token( - model=model, usage=usage, custom_llm_provider=provider, model_info=price_table + model=model, + usage=usage, + custom_llm_provider=provider, + model_info=price_table, + data_residency=data_residency, + optional_params=optional_params, ) return prompt_cost + completion_cost @@ -48,7 +55,12 @@ def cost_calculator( # does not itemize output and splitting text/image when it does. if getattr(usage, "input_tokens", None) is not None: token_based_cost: Final = calculate_image_response_cost_from_usage( - model=model, image_response=image_response, custom_llm_provider=provider, model_info=price_table + model=model, + image_response=image_response, + custom_llm_provider=provider, + model_info=price_table, + data_residency=data_residency, + optional_params=optional_params, ) if token_based_cost is not None: return token_based_cost @@ -57,7 +69,12 @@ def cost_calculator( # cost via generic_cost_per_token (text rate) instead of returning 0.0. if isinstance(usage, Usage): prompt_cost, completion_cost = generic_cost_per_token( - model=model, usage=usage, custom_llm_provider=provider, model_info=price_table + model=model, + usage=usage, + custom_llm_provider=provider, + model_info=price_table, + data_residency=data_residency, + optional_params=optional_params, ) return prompt_cost + completion_cost From 5c2c6d312c0e933160cbb250d7047ed9b0fe914f Mon Sep 17 00:00:00 2001 From: Aishwary Dongre Date: Thu, 15 Oct 2026 14:43:23 +0530 Subject: [PATCH 2/2] fix: pass data_residency parameter to prevent undefined variable error - Add data_residency parameter to route_image_generation_cost_calculator signature - Pass data_residency from completion_cost to image cost calculator - Fixes HIGH severity issue: undefined variable causing spend limit bypass --- litellm/cost_calculator.py | 1 + litellm/litellm_core_utils/llm_cost_calc/utils.py | 1 + 2 files changed, 2 insertions(+) diff --git a/litellm/cost_calculator.py b/litellm/cost_calculator.py index 918b95280be..b12363b557f 100644 --- a/litellm/cost_calculator.py +++ b/litellm/cost_calculator.py @@ -1663,6 +1663,7 @@ def completion_cost( call_type=call_type, model_info=_deployment_model_info(litellm_logging_obj, custom_pricing, router_model_id), vertex_location=vertex_location, + data_residency=data_residency, ) elif call_type in _VIDEO_CALL_TYPES: ### VIDEO GENERATION COST CALCULATION ### diff --git a/litellm/litellm_core_utils/llm_cost_calc/utils.py b/litellm/litellm_core_utils/llm_cost_calc/utils.py index 6709bf7a0a5..085bdd0376a 100644 --- a/litellm/litellm_core_utils/llm_cost_calc/utils.py +++ b/litellm/litellm_core_utils/llm_cost_calc/utils.py @@ -1953,6 +1953,7 @@ class CostCalculatorUtils: call_type: str | None = None, model_info: ModelInfo | None = None, vertex_location: str | None = None, + data_residency: str | None = None, ) -> float: """ Route the image generation cost calculator based on the custom_llm_provider