headroomlabs-ai/headroom · error · ValueError

Model '{model}' does not have batch output pricing

Error message

Model '{model}' does not have batch output pricing

What it means

Thrown by the pricing registry's cost estimator when a request includes batch output tokens but the model's pricing entry has no batch_output_per_1m rate (it is None). Pricing records only carry batch output rates for models that publish discounted Batch API output pricing, so asking to price batch output for any other model is rejected rather than silently priced at zero. It mirrors the batch-input check directly above it in the same method.

Source

Thrown at headroom/pricing/registry.py:173

            }
            total_cost += cached_cost

        # Batch input tokens
        if batch_input_tokens > 0:
            if pricing.batch_input_per_1m is None:
                raise ValueError(f"Model '{model}' does not have batch input pricing")
            batch_input_cost = (batch_input_tokens / 1_000_000) * pricing.batch_input_per_1m
            breakdown["batch_input"] = {
                "tokens": batch_input_tokens,
                "rate_per_1m": pricing.batch_input_per_1m,
                "cost_usd": batch_input_cost,
            }
            total_cost += batch_input_cost

        # Batch output tokens
        if batch_output_tokens > 0:
            if pricing.batch_output_per_1m is None:
                raise ValueError(f"Model '{model}' does not have batch output pricing")
            batch_output_cost = (batch_output_tokens / 1_000_000) * pricing.batch_output_per_1m
            breakdown["batch_output"] = {
                "tokens": batch_output_tokens,
                "rate_per_1m": pricing.batch_output_per_1m,
                "cost_usd": batch_output_cost,
            }
            total_cost += batch_output_cost

        return CostEstimate(
            cost_usd=total_cost,
            breakdown=breakdown,
            pricing_date=self.last_updated,
            is_stale=self.is_stale(),
            warning=self.staleness_warning(),
        )

View on GitHub (pinned to 322425c43b)

Solutions

  1. Check pricing.batch_output_per_1m is not None before including batch_output_tokens in the call, or pass batch_output_tokens=0
  2. Update the model's pricing entry (registry data / pricing file) to include a batch output rate if the provider actually publishes one
  3. If the model truly has no batch output discount, route batch output tokens through the regular output_tokens argument so they are priced at the standard rate

Example fix

// before
estimate = registry.estimate(
    model="my-model",
    input_tokens=1000,
    output_tokens=0,
    batch_input_tokens=50000,
    batch_output_tokens=8000,   # raises: no batch output pricing
)

// after
pricing = registry.get_pricing("my-model")
batch_out = 8000 if pricing.batch_output_per_1m is not None else 0
estimate = registry.estimate(
    model="my-model",
    input_tokens=1000,
    output_tokens=0 if pricing.batch_output_per_1m is not None else 8000,
    batch_input_tokens=50000,
    batch_output_tokens=batch_out,
)
Defensive patterns

Strategy: validation

Validate before calling

from headroom.pricing.registry import PricingRegistry

pricing = registry.get_pricing(model)
has_batch_out = pricing.batch_output_per_1m is not None
estimate = registry.estimate(
    model=model,
    input_tokens=in_tok,
    output_tokens=0 if has_batch_out else out_tok,
    batch_input_tokens=batch_in if pricing.batch_input_per_1m is not None else 0,
    batch_output_tokens=batch_out if has_batch_out else 0,
)

Type guard

def supports_batch_output_pricing(pricing) -> bool:
    return pricing.batch_output_per_1m is not None

Try / catch

try:
    estimate = registry.estimate(...)
except ValueError as e:
    if 'batch output pricing' in str(e):
        # re-price batch output at standard rates
        ...
    raise

Prevention

When it happens

Trigger: Calling registry.estimate/estimate_cost with batch_output_tokens > 0 for a model whose pricing row has batch_output_per_1m=None (e.g. a model that only lists batch input pricing, or a custom pricing entry added without the batch output field). Passing batch usage rows from a Batch API job through the standard pricing path.

Common situations: Custom/self-hosted model pricing added to the registry without batch fields; a provider that discounts batch input but not output; using a batch report against an older pricing snapshot that predates batch output rates.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/1012dba32936b483. Report an issue: GitHub.