{"record":{"id":"19e5195b23c3243e","repo":"BerriAI/litellm","slug":"invalid-budget-reset-time-raw-r-expected-a-24-h","errorCode":null,"errorMessage":"Invalid budget_reset_time {raw!r}; expected a 24-hour 'HH:MM' or 'HH:MM:SS' string, e.g. \"12:00\"","messagePattern":"Invalid budget_reset_time (.+?); expected a 24-hour 'HH:MM' or 'HH:MM:SS' string, e\\.g\\. \"12:00\"","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/common_utils/timezone_utils.py","lineNumber":39,"sourceCode":"\n\ndef parse_budget_reset_time(raw: object) -> time:\n    \"\"\"Parse a `budget_reset_time` config value (e.g. \"12:00\") into a `time`.\n\n    Falls back to midnight when unset; raises a clear error on a malformed value\n    so a bad config fails loudly at startup instead of silently resetting at midnight.\n    \"\"\"\n    if raw is None or raw == \"\":\n        return time(0, 0)\n    if not isinstance(raw, str):\n        raise ValueError(f\"Invalid budget_reset_time {raw!r}; must be a quoted 24-hour 'HH:MM' string, e.g. \\\"12:00\\\"\")\n    for fmt in (\"%H:%M\", \"%H:%M:%S\"):\n        try:\n            parsed = datetime.strptime(raw, fmt)\n            return time(hour=parsed.hour, minute=parsed.minute, second=parsed.second)\n        except ValueError:\n            continue\n    raise ValueError(\n        f\"Invalid budget_reset_time {raw!r}; expected a 24-hour 'HH:MM' or 'HH:MM:SS' string, e.g. \\\"12:00\\\"\"\n    )\n\n\ndef get_budget_reset_timezone() -> str:\n    \"\"\"\n    Get the budget reset timezone from litellm_settings.\n    Falls back to UTC if not specified.\n\n    litellm_settings values are set as attributes on the litellm module\n    by proxy_server.py at startup (via setattr(litellm, key, value)).\n    \"\"\"\n    return getattr(litellm, \"timezone\", None) or \"UTC\"\n\n\ndef get_budget_reset_settings() -> BudgetResetSettings:\n    \"\"\"Build validated reset settings from litellm_settings. Raises on a malformed\n    `budget_reset_time`, which lets the proxy fail fast at startup.\"\"\"","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/common_utils/timezone_utils.py#L21-L57","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nbudget_reset_time: \"9:00 PM\"\n\n# after\nbudget_reset_time: \"21:00\"","handlingStrategy":"validation","validationCode":"from datetime import datetime\n\ndef check_budget_reset_time(raw: str) -> bool:\n    for fmt in (\"%H:%M\", \"%H:%M:%S\"):\n        try:\n            datetime.strptime(raw, fmt)\n            return True\n        except ValueError:\n            continue\n    return False\n\nassert check_budget_reset_time(\"21:00\"), \"use 24-hour HH:MM\"","typeGuard":"import re\nHH_MM = re.compile(r\"^(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d)?$\")\n\ndef is_hh_mm_string(s: object) -> bool:\n    return isinstance(s, str) and bool(HH_MM.fullmatch(s))","tryCatchPattern":"try:\n    parse_budget_reset_time(raw)\nexcept ValueError:\n    raw = \"00:00\"  # or reject the config before deploy\n    log.warning(\"invalid budget_reset_time %r, defaulting to midnight\", raw)","preventionTips":["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."],"tags":["litellm-proxy","config","time-format","validation","budget"],"backgroundTag":"config-validation-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}