BerriAI/litellm · error · ValueError
Invalid budget_reset_time {raw!r}; expected a 24-hour 'HH:MM
Error message
Invalid budget_reset_time {raw!r}; expected a 24-hour 'HH:MM' or 'HH:MM:SS' string, e.g. "12:00" What it means
ValueError from parse_budget_reset_time in litellm/proxy/common_utils/timezone_utils.py when the value is a string but does not match the 24-hour '%H:%M' or '%H:%M:%S' formats. strptime is tried for both formats and the ValueError re-raised with a clear message so a malformed time fails at proxy startup rather than being silently treated as midnight.
Source
Thrown at litellm/proxy/common_utils/timezone_utils.py:39
def parse_budget_reset_time(raw: object) -> time:
"""Parse a `budget_reset_time` config value (e.g. "12:00") into a `time`.
Falls back to midnight when unset; raises a clear error on a malformed value
so a bad config fails loudly at startup instead of silently resetting at midnight.
"""
if raw is None or raw == "":
return time(0, 0)
if not isinstance(raw, str):
raise ValueError(f"Invalid budget_reset_time {raw!r}; must be a quoted 24-hour 'HH:MM' string, e.g. \"12:00\"")
for fmt in ("%H:%M", "%H:%M:%S"):
try:
parsed = datetime.strptime(raw, fmt)
return time(hour=parsed.hour, minute=parsed.minute, second=parsed.second)
except ValueError:
continue
raise ValueError(
f"Invalid budget_reset_time {raw!r}; expected a 24-hour 'HH:MM' or 'HH:MM:SS' string, e.g. \"12:00\""
)
def get_budget_reset_timezone() -> str:
"""
Get the budget reset timezone from litellm_settings.
Falls back to UTC if not specified.
litellm_settings values are set as attributes on the litellm module
by proxy_server.py at startup (via setattr(litellm, key, value)).
"""
return getattr(litellm, "timezone", None) or "UTC"
def get_budget_reset_settings() -> BudgetResetSettings:
"""Build validated reset settings from litellm_settings. Raises on a malformed
`budget_reset_time`, which lets the proxy fail fast at startup."""View on GitHub (pinned to 77b7c6c40c)
Solutions
- Use strict 24-hour HH:MM ("12:00", "09:30") or HH:MM:SS ("09:30:15") strings.
- Check for out-of-range values: hours 00-23, minutes/seconds 00-59 — "24:00" must be written "00:00".
- Strip stray whitespace and confirm the value is quoted in YAML before restarting the proxy.
Example fix
# before budget_reset_time: "9:00 PM" # after budget_reset_time: "21:00"
Defensive patterns
Strategy: validation
Validate before calling
from datetime import datetime
def check_budget_reset_time(raw: str) -> bool:
for fmt in ("%H:%M", "%H:%M:%S"):
try:
datetime.strptime(raw, fmt)
return True
except ValueError:
continue
return False
assert check_budget_reset_time("21:00"), "use 24-hour HH:MM" Type guard
import re
HH_MM = re.compile(r"^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$")
def is_hh_mm_string(s: object) -> bool:
return isinstance(s, str) and bool(HH_MM.fullmatch(s)) Try / catch
try:
parse_budget_reset_time(raw)
except ValueError:
raw = "00:00" # or reject the config before deploy
log.warning("invalid budget_reset_time %r, defaulting to midnight", raw) Prevention
- Standardize on 24-hour notation in all time settings; forbid AM/PM strings in config review.
- Add a config-lint step that runs parse_budget_reset_time over the merged settings at deploy time.
- Property-test config generators against the HH:MM regex to catch locale-formatted output.
When it happens
Trigger: budget_reset_time: "9:00 AM" or "12 noon" (12-hour/AM-PM style); "24:30" or "12:99" (out-of-range hours/minutes); "12-00" or "1200" (wrong separators); values with trailing whitespace like "12:00 " that strptime rejects.
Common situations: Porting cron-style or locale-specific time strings from other tooling into litellm budget config; hand-editing the config and using 12-hour times; a CI-generated config writing locale-formatted times.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- Invalid budget_reset_time {raw!r}; must be a quoted 24-hour
- mcp_tools_config must be a list of dictionaries
- Custom code guardrail requires a guardrail_name
- Custom code guardrail requires 'custom_code' in litellm_para
- max_budget cannot be negative. Received: {data.max_budget}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/19e5195b23c3243e.
Report an issue: GitHub.