BerriAI/litellm · error · ValueError

Model is None and does not exist in passed completion_respon

Error message

Model is None and does not exist in passed completion_response. Passed completion_response={completion_response}, model={model}

What it means

In completion_cost's no-usage branch, LiteLLM falls back to counting tokens locally with token_counter, which needs a model name. If the completion_response carries neither usage nor a model, and the caller passed model=None, it cannot even estimate tokens and raises ValueError echoing the response object.

Source

Thrown at litellm/cost_calculator.py:1307

                    total_time = getattr(completion_response, "_response_ms", 0)

                    hidden_params = getattr(completion_response, "_hidden_params", None)
                    if hidden_params is not None:
                        custom_llm_provider = hidden_params.get("custom_llm_provider", custom_llm_provider or None)
                        region_name = hidden_params.get("region_name", region_name)

                        # For Gemini/Vertex AI responses, trafficType is stored in
                        # provider_specific_fields.  Map it to the service_tier used
                        # by the cost key lookup (_priority / _flex suffixes) so that
                        # ON_DEMAND_PRIORITY requests are billed at priority prices.
                        if service_tier is None:
                            provider_specific = hidden_params.get("provider_specific_fields") or {}
                            raw_traffic_type = provider_specific.get("traffic_type")
                            if raw_traffic_type:
                                service_tier = _map_traffic_type_to_service_tier(raw_traffic_type)
                else:
                    if model is None:
                        raise ValueError(
                            f"Model is None and does not exist in passed completion_response. Passed completion_response={completion_response}, model={model}"
                        )
                    if len(messages) > 0:
                        prompt_tokens = token_counter(model=model, messages=messages)
                    elif len(prompt) > 0:
                        prompt_tokens = token_counter(model=model, text=prompt)
                    completion_tokens = token_counter(model=model, text=completion)

                # Handle A2A calls before model check - A2A doesn't require a model
                if call_type in _A2A_CALL_TYPES:
                    from litellm.a2a_protocol.cost_calculator import A2ACostCalculator

                    return A2ACostCalculator.calculate_a2a_cost(litellm_logging_obj=litellm_logging_obj)

                if model is None:
                    raise ValueError(
                        f"Model is None and does not exist in passed completion_response. Passed completion_response={completion_response}, model={model}"
                    )

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass model explicitly: completion_cost(completion_response=resp, model='gpt-4o').
  2. Set usage on the response (resp['usage'] = Usage(prompt_tokens=..., completion_tokens=...)) so the local-count fallback is skipped.
  3. Ensure custom provider transformations populate ModelResponse.model and usage.
  4. In tests, clone a recorded real response rather than constructing an empty ModelResponse.

Example fix

# before
resp = ModelResponse(choices=[...])  # no model, no usage
cost = litellm.completion_cost(completion_response=resp)

# after
resp = ModelResponse(choices=[...], model="gpt-4o-mini")
cost = litellm.completion_cost(completion_response=resp, model="gpt-4o-mini")
Defensive patterns

Strategy: validation

Validate before calling

if not completion_response.get("usage") and model is None:
    model = completion_response.get("model") or request_model
    if model is None:
        raise ValueError("response has neither usage nor model; cannot count tokens")

Type guard

def cost_countable(resp, model: str | None) -> bool:
    return bool(resp.get("usage")) or model is not None or bool(resp.get("model"))

Try / catch

try:
    cost = litellm.completion_cost(completion_response=resp, model=model)
except ValueError as e:
    if "Model is None" in str(e):
        cost = None  # skip billing for this response; alert
    else:
        raise

Prevention

When it happens

Trigger: completion_cost(completion_response=resp) where resp has no 'usage' and no 'model' field and no model argument was supplied; common with hand-built ModelResponse objects in tests or post-processed responses.

Common situations: Mocked/stub responses in unit tests; response objects serialized through a layer that drops fields; custom providers whose transformations don't populate model or usage.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/f39c69652e84503f. Report an issue: GitHub.