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
- Pass model explicitly: completion_cost(completion_response=resp, model='gpt-4o').
- Set usage on the response (resp['usage'] = Usage(prompt_tokens=..., completion_tokens=...)) so the local-count fallback is skipped.
- Ensure custom provider transformations populate ModelResponse.model and usage.
- 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
- Thread the request model into every cost calculation call.
- Populate usage on responses in tests: resp['usage'] = Usage(prompt_tokens=10, completion_tokens=5).
- Alert on skipped cost calculations rather than silently dropping them.
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
- Invalid arg. Model cannot be none.
- usage object and custom_llm_provider must be provided for re
- OCR response usage_info is None
- OCR response pages_processed is None
- prompt_characters must be provided for tts calls. prompt_cha
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/f39c69652e84503f.
Report an issue: GitHub.