#41605·litellm

[Bug]: Synchronous Azure deployment pricing can be recorded as $0

Author: cmcfaddenCreated Sep 17, 2026Updated Sep 17, 2026
Labelsbugproxyllm translation

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

Successful Azure AI Foundry requests using azure_ai/gpt-5.6-luna intermittently record a total cost of $0.00000000 even though the request has nonzero prompt and completion tokens and the deployment has pricing configured.

The issue appears specific to the synchronous completion path. Comparable acompletion requests using the same model, provider, API base, and deployment record the expected cost.

The affected model-map metadata resolves to azure/azure_ai/gpt-5.6-luna with input_cost_per_token: 0 and output_cost_per_token: 0, while the deployment-scoped pricing is nonzero. Affected requests therefore fall back to the zero-valued public model entry.

It's possible this was fixed in v1.101 due to the change in Azure/Azure_ai bridging, but I'm not clear that the underyling issue doesn't still exist with completion vs aacompletion potentially causing lookup failures? Opening this bug for review.

User Flow

Before a (hypothetical) fix:

  1. A developer configures an Azure AI Foundry deployment for azure_ai/gpt-5.6-luna with nonzero deployment pricing.
  2. They send a synchronous chat completion request through the LiteLLM Proxy.
  3. Azure returns nonzero usage, including prompt-cache and completion/reasoning tokens.
  4. LiteLLM records the request successfully but the spend log and dashboard show $0.00000000.
  5. The developer cannot rely on spend tracking or budgets for these requests.

After a (hypothetical) fix:

  1. The developer sends the same synchronous request.
  2. LiteLLM preserves the selected deployment's model ID and pricing context through response metadata and cost calculation.
  3. LiteLLM applies the deployment's input, cache-read, cache-creation, output, and reasoning rates.
  4. The spend log and dashboard show the same nonzero cost that the asynchronous path records.
  5. Budgets and usage reports reflect the actual request cost.

Proof the bug occurs

Config / setup:

  • Repository: BerriAI/litellm
  • Provider: Azure AI Foundry
  • Model: azure_ai/gpt-5.6-luna
  • Displayed provider: azure
  • API base: Azure AI Foundry endpoint
  • Call type affected: completion
  • Comparable working path: acompletion
  • Response cache: LiteLLM cache miss; provider prompt-cache usage is present

Observed zero-cost request:

json
{
  "total_tokens": 16302,
  "prompt_tokens": 13955,
  "completion_tokens": 2347,
  "prompt_tokens_details": {
    "cached_tokens": 2092,
    "cache_write_tokens": 11860,
    "cache_creation_tokens": 11860
  },
  "completion_tokens_details": {
    "reasoning_tokens": 1536
  },
  "cost_breakdown": {
    "input_cost": 0,
    "output_cost": 0,
    "total_cost": 0
  },
  "model_map_information": {
    "model_map_key": "azure_ai/gpt-5.6-luna",
    "model_map_value": {
      "key": "azure/azure_ai/gpt-5.6-luna",
      "litellm_provider": "azure",
      "input_cost_per_token": 0,
      "output_cost_per_token": 0,
      "cache_read_input_token_cost": null,
      "cache_creation_input_token_cost": null
    }
  }
}

Working comparable request:

  • prompt_tokens: 29076
  • completion_tokens: 4955
  • cache_read_tokens: 2092
  • cache_creation_tokens: 27337
  • Recorded total: $0.01321485

A second billed metadata sample shows the deployment-scoped rates being applied successfully:

  • input_cost: $0.00687669
  • output_cost: $0.00626280
  • cache_read_cost: $0.00004184
  • cache_creation_cost: $0.00683425
  • reasoning_cost: $0.00112440
  • total_cost: $0.01313949

The suspected propagation issue is in the synchronous response metadata path. ResponseMetadata.set_hidden_params() derives router_model_id only from kwargs.get("model_info", {}).get("id") before calling logging_obj._response_cost_calculator(). If that request-local model_info is absent, the calculator falls back to the public model-map entry and stamps response._hidden_params["response_cost"] = 0.0. Later _response_cost_calculator() returns the existing hidden response cost immediately instead of retrying with logging_obj.get_router_model_id().

Relevant code paths:

  • litellm/litellm_core_utils/llm_response_utils/response_metadata.py: ResponseMetadata.set_hidden_params()
  • litellm/litellm_core_utils/litellm_logging.py: Logging._response_cost_calculator() and Logging.get_router_model_id()
  • litellm/cost_calculator.py: _select_model_name_for_cost_calc()
  • litellm/utils.py: synchronous client.wrapper() response metadata update versus wrapper_async() success logging

The exact runtime values that would confirm the issue are:

kwargs["model_info"]
logging_obj.litellm_params["model_info"]
logging_obj.litellm_params["metadata"]["model_info"]
logging_obj.litellm_params["litellm_metadata"]["model_info"]
logging_obj.get_router_model_id()
use_custom_pricing_for_model(logging_obj.litellm_params)
result._hidden_params

Version or commit: not provided.

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on ?

v1.100.0

Twitter / LinkedIn details

No response