BerriAI/litellm · error · ValueError

cost for tts call is None. prompt_cost={_prompt_cost}, compl

Error message

cost for tts call is None. prompt_cost={_prompt_cost}, completion_cost={_completion_cost}, model={model_without_prefix}, custom_llm_provider={custom_llm_provider}, prompt_characters={prompt_characters}, completion_characters={completion_characters}

What it means

After a per-character TTS cost lookup succeeds, _generic_cost_per_character must return numeric prompt/completion costs. If either comes back None (model missing per-character pricing in the cost map despite the metric selection, or a custom-cost path returning None), the calculator refuses to emit a None cost and raises ValueError with full context.

Source

Thrown at litellm/cost_calculator.py:507

        speech_model_info = litellm.get_model_info(model=model_without_prefix, custom_llm_provider=custom_llm_provider)
        cost_metric: Final = select_cost_metric_for_model(speech_model_info)
        prompt_cost: float = 0.0
        completion_cost: float = 0.0
        if cost_metric == "cost_per_character":
            if prompt_characters is None:
                raise ValueError(
                    f"prompt_characters must be provided for tts calls. prompt_characters={prompt_characters}, model={model}, custom_llm_provider={custom_llm_provider}, call_type={call_type}"
                )
            _prompt_cost, _completion_cost = _generic_cost_per_character(
                model=model_without_prefix,
                custom_llm_provider=custom_llm_provider,
                prompt_characters=prompt_characters,
                completion_characters=0,
                custom_prompt_cost=None,
                custom_completion_cost=0,
            )
            if _prompt_cost is None or _completion_cost is None:
                raise ValueError(
                    f"cost for tts call is None. prompt_cost={_prompt_cost}, completion_cost={_completion_cost}, model={model_without_prefix}, custom_llm_provider={custom_llm_provider}, prompt_characters={prompt_characters}, completion_characters={completion_characters}"
                )
            prompt_cost = _prompt_cost
            completion_cost = _completion_cost
        elif cost_metric == "cost_per_token":
            prompt_cost, completion_cost = generic_cost_per_token(
                model=model_without_prefix,
                usage=usage_block,
                custom_llm_provider=custom_llm_provider,
                service_tier=service_tier,
                data_residency=data_residency,
            )

        return prompt_cost, completion_cost
    elif call_type == "arerank" or call_type == "rerank":
        return rerank_cost(
            model=model,
            custom_llm_provider=custom_llm_provider,

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Update LiteLLM to pick up current pricing data (pip install -U litellm).
  2. Register pricing for the model with litellm.register_model({model: {'input_cost_per_character': ...}}).
  3. Verify the model entry has character pricing keys via litellm.get_model_info(model).
  4. If pricing genuinely is unknown, compute cost yourself from provider billing instead of relying on completion_cost.

Example fix

# before
cost = litellm.completion_cost(model="tts-1-hd", call_type="speech",
                             prompt="hi", prompt_characters=2)  # ValueError: cost is None

# after
litellm.register_model({
    "tts-1-hd": {"input_cost_per_character": 0.000015},
})
cost = litellm.completion_cost(model="tts-1-hd", call_type="speech",
                             prompt="hi", prompt_characters=2)
Defensive patterns

Strategy: fallback

Validate before calling

info = litellm.get_model_info(model=model) or {}
if not info.get("input_cost_per_character"):
    raise MissingPricing(model)  # register pricing before calling

Type guard

def has_character_pricing(model: str) -> bool:
    try:
        info = litellm.get_model_info(model=model) or {}
    except Exception:
        return False
    return info.get("input_cost_per_character") is not None

Try / catch

try:
    cost = litellm.completion_cost(...)
except ValueError as e:
    if "cost for tts call is None" in str(e):
        litellm.register_model({model: {"input_cost_per_character": fallback_price}})
        cost = litellm.completion_cost(...)
    else:
        raise

Prevention

When it happens

Trigger: A speech model whose model_info selects cost_per_character but whose cost map entry lacks input_cost_per_character / custom prices; a LiteLLM version whose model_prices file omits the TTS model's character pricing; custom_cost set to None paths.

Common situations: Brand-new or regional TTS models not yet in the bundled model_prices_and_context_window.json; stale pricing data after upgrades; forked cost maps that dropped pricing keys.

Related errors


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