BerriAI/litellm · warning · HTTPException
Fixed margin amount for {provider} must be a number
Error message
Fixed margin amount for {provider} must be a number What it means
Validation error (HTTP 400) from PATCH /config/cost_margin_config in the complex dict format: the optional 'fixed_amount' field is present but is not an int/float. fixed_amount is an absolute dollar surcharge added per request, so it must be a bare number.
Source
Thrown at litellm/proxy/management_endpoints/cost_tracking_settings.py:390
)
elif isinstance(margin_value, dict):
# Complex format: {"percentage": 0.08, "fixed_amount": 0.0005}
if "percentage" in margin_value:
percentage = margin_value["percentage"]
if not isinstance(percentage, (int, float)):
raise HTTPException(
status_code=400,
detail=f"Margin percentage for {provider} must be a number",
)
if not (0 <= percentage <= 10):
raise HTTPException(
status_code=400,
detail=f"Margin percentage for {provider} must be between 0 and 10 (0% to 1000%)",
)
if "fixed_amount" in margin_value:
fixed_amount = margin_value["fixed_amount"]
if not isinstance(fixed_amount, (int, float)):
raise HTTPException(
status_code=400,
detail=f"Fixed margin amount for {provider} must be a number",
)
if fixed_amount < 0:
raise HTTPException(
status_code=400,
detail=f"Fixed margin amount for {provider} must be non-negative",
)
if not margin_value: # Empty dict
raise HTTPException(
status_code=400,
detail=f"Margin config for {provider} cannot be empty. Must include 'percentage' and/or 'fixed_amount'",
)
else:
raise HTTPException(
status_code=400,
detail=f"Margin for {provider} must be a number (percentage) or dict with 'percentage' and/or 'fixed_amount'",
)View on GitHub (pinned to 77b7c6c40c)
Solutions
- Send fixed_amount as a bare number: {"fixed_amount": 0.001}.
- Cast with float() when constructing payloads from string sources.
- Omit the key if you don't want a fixed component.
Example fix
# before
{"openai": {"fixed_amount": "0.001"}}
# after
{"openai": {"fixed_amount": 0.001}} Defensive patterns
Strategy: type-guard
Validate before calling
for provider, margin in cost_margin_config.items():
if isinstance(margin, dict) and "fixed_amount" in margin:
fa = margin["fixed_amount"]
if isinstance(fa, str):
margin["fixed_amount"] = fa = float(fa)
assert isinstance(fa, (int, float)) and not isinstance(fa, bool), f"{provider}.fixed_amount must be numeric" Type guard
def is_valid_fixed_amount(m: dict) -> bool:
return "fixed_amount" not in m or (
isinstance(m["fixed_amount"], (int, float))
and not isinstance(m["fixed_amount"], bool)
and m["fixed_amount"] >= 0
) Prevention
- Monetary values are bare numbers in USD-per-request units.
- Reject stringified currency amounts at the config-source layer.
When it happens
Trigger: Sending {"fixed_amount": "0.001"} (string), null, or a list; template/env-driven values that arrive as strings.
Common situations: Currency values pasted as strings from billing configs; JSON built via string templates where every value is quoted.
Related errors
- Discount for {provider} must be a number
- Margin percentage for {provider} must be a number
- Margin for {provider} must be a number (percentage) or dict
- Invalid provider(s): {', '.join(invalid_providers)}. Must be
- Discount for {provider} must be between 0 and 1 (0% to 100%)
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/df3a6824c591e96a.
Report an issue: GitHub.