BerriAI/litellm · warning · HTTPException
Invalid budget_duration '{budget_duration}'. Use a format li
Error message
Invalid budget_duration '{budget_duration}'. Use a format like '1h', '24h', '7d', or '30d'. What it means
validate_budget_duration guards the budget_duration field on key/user/team/budget creation: it parses the string with duration_in_seconds and computes the reset time via get_budget_reset_time inside try/except (ValueError, OverflowError), mapping any failure to HTTP 400 with the supported-format hint. It rejects three classes: unparseable strings ('1 month', 'monthly'), non-positive durations ('0h', '-30d' — which would resolve to a permanently-due reset time), and durations whose date arithmetic overflows (e.g. '999999999d').
Source
Thrown at litellm/proxy/management_endpoints/common_utils.py:46
budget reset job.
A non-positive duration also resolves to a reset time of "now", which leaves
the row permanently due: the reset job re-reads it every tick and, once
enough of them exist, they fill each batch and starve every other tenant's
reset.
"""
if budget_duration is None:
return
from litellm.litellm_core_utils.duration_parser import duration_in_seconds
from litellm.proxy.common_utils.timezone_utils import get_budget_reset_time
try:
if duration_in_seconds(budget_duration) <= 0:
raise ValueError("budget_duration must be positive")
get_budget_reset_time(budget_duration=budget_duration)
except (ValueError, OverflowError):
raise HTTPException(
status_code=400,
detail={
"error": f"Invalid budget_duration '{budget_duration}'. Use a format like '1h', '24h', '7d', or '30d'."
},
)
from litellm._logging import verbose_proxy_logger
from litellm.caching import DualCache
from litellm.proxy._types import (
KeyRequestBase,
LiteLLM_ManagementEndpoint_MetadataFields,
LiteLLM_ManagementEndpoint_MetadataFields_Premium,
LiteLLM_OrganizationTable,
LiteLLM_ProjectTable,
LiteLLM_TeamTable,
LiteLLM_UserTable,
LitellmUserRoles,View on GitHub (pinned to 77b7c6c40c)
Solutions
- Use a supported plain value: '1h', '24h', '7d', '30d' (number + one time unit, no spaces)
- For non-positive or overflow mistakes, pick a real positive window within date-math limits
- Validate the format client-side with a regex like ^\d+[smhdw]$ before sending
Example fix
# before
curl -X POST http://localhost:4000/key/generate -d '{"budget_duration": "30days"}'
# 400 Invalid budget_duration '30days'. Use a format like '1h', '24h', '7d', or '30d'.
# after
curl -X POST http://localhost:4000/key/generate -d '{"budget_duration": "30d"}' Defensive patterns
Strategy: validation
Validate before calling
import re
DURATION_RE = re.compile(r"^\d+[smhdw]$")
def valid_budget_duration(d: str | None) -> bool:
if d is None:
return True
if not DURATION_RE.match(d):
return False
n = int(d[:-1])
return n > 0 and n * 10_000 < 10**9 # stay far below date-math overflow
assert valid_budget_duration(payload.get("budget_duration")), "use '1h', '24h', '7d', or '30d'" Type guard
from typing import TypeGuard
import re
_DURATION = re.compile(r"^([1-9]\d{0,6})[smhdw]$")
def is_valid_budget_duration(value: object) -> TypeGuard[str]:
"""Narrows to a positive, non-overflowing duration string the proxy accepts."""
if not isinstance(value, str):
return False
m = _duration.match(value)
return bool(m) and int(m.group(1)) > 0 Try / catch
import httpx
try:
r = httpx.post(f"{PROXY_URL}/key/generate", json=payload, headers=hdrs)
r.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 400 and "Invalid budget_duration" in e.response.text:
payload["budget_duration"] = "30d" # safe default; or surface to the user
r = httpx.post(f"{PROXY_URL}/key/generate", json=payload, headers=hdrs)
r.raise_for_status()
else:
raise Prevention
- Offer a dropdown of durations in UIs instead of free text
- Reject '0h'/'-1d' and month-style strings ('1mo', '1 month') client-side
- Remember no default is applied: omit budget_duration entirely when unsure
When it happens
Trigger: POST /key/generate or /team/new with budget_duration='30days', '0h', '-1d', '1mo' (unsupported unit), or an absurd magnitude that overflows timedelta/date math; copying durations from cron or Kubernetes notation ('24h0m0s') which the parser does not accept.
Common situations: UIs offering free-text duration inputs; migrating configs from systems using ISO-8601 durations (P30D) or human phrases ('1 month'); users assuming months are supported because budgets are monthly.
Related errors
- spend must be a finite number. Received: {spend}
- Invalid key format.
- Invalid key_alias format. Must be 2-255 characters, start/en
- Unsupported image format: {image_format}. Supported formats:
- mcp_tools_config must be a list of dictionaries
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/987eb9068627a8de.
Report an issue: GitHub.