BerriAI/litellm · error · ValueError
end_time is required, got={end_time} of type {type(end_time)
Error message
end_time is required, got={end_time} of type {type(end_time)} What it means
Same normalization helper as start_time: end_time must be a datetime.datetime or a float. Any other type — None, int, string — raises this ValueError. The strictness exists because the helper converts timings to floats for span/log records; ints are notably not accepted by the isinstance(., float) check.
Source
Thrown at litellm/litellm_core_utils/litellm_logging.py:4727
completion_start_time: Union[dt_object, float]
Returns:
Tuple[float, float, float]: A tuple containing the start time, end time, and completion start time as floats.
"""
if isinstance(start_time, datetime.datetime):
start_time_float = start_time.timestamp()
elif isinstance(start_time, float):
start_time_float = start_time
else:
raise ValueError(f"start_time is required, got={start_time} of type {type(start_time)}")
if isinstance(end_time, datetime.datetime):
end_time_float = end_time.timestamp()
elif isinstance(end_time, float):
end_time_float = end_time
else:
raise ValueError(f"end_time is required, got={end_time} of type {type(end_time)}")
if isinstance(completion_start_time, datetime.datetime):
completion_start_time_float = completion_start_time.timestamp()
elif isinstance(completion_start_time, float):
completion_start_time_float = completion_start_time
else:
completion_start_time_float = end_time_float
return start_time_float, end_time_float, completion_start_time_float
@staticmethod
def append_system_prompt_messages(kwargs: dict | None = None, messages: Any | None = None):
"""
Append system prompt messages to the messages
"""
if kwargs is not None:
if kwargs.get("system") is not None and isinstance(kwargs.get("system"), str):
if messages is None:View on GitHub (pinned to 6c2dcb801b)
Solutions
- Use datetime objects or explicitly cast to float: end_time=float(end_time)
- Guard None with a fallback before logging: end_time or datetime.datetime.now()
- In custom handlers, mirror LiteLLM's own pattern of always creating both timestamps at handler entry
Example fix
# before end_time = int(time.time()) # ValueError: end_time is required # after end_time = float(time.time()) # or end_time = datetime.datetime.now(datetime.timezone.utc)
Defensive patterns
Strategy: type-guard
Validate before calling
import datetime
def safe_end_time(t, fallback=None):
if isinstance(t, datetime.datetime) or isinstance(t, float):
return t
return fallback if fallback is not None else datetime.datetime.now() Type guard
import datetime
def is_valid_time_value(t) -> bool:
return isinstance(t, datetime.datetime) or isinstance(t, float) Prevention
- Never forward None or int timestamps into litellm logging helpers
- Set end_time unconditionally in failure handlers (use 'now' when unknown)
- Keep timestamps as datetime objects end-to-end; convert to float only at the boundary
When it happens
Trigger: Passing end_time as an int epoch (int(time.time())), None (unset on early failure paths), or a serialized string into Logging methods / custom callback handlers that reach this converter.
Common situations: Custom callbacks computing durations with integer arithmetic; JSON round-tripping turning datetimes into strings; failure handlers where end_time was never set before logging.
Related errors
- start_time is required, got={start_time} of type {type(start
- usage is required, got={usage} of type {type(usage)}
- response must be of type OCRResponse got type={type(response
- Promptlayer did not successfully log the response!
- Callback param '{param}' (from {source}) contains an 'os.env
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/08aa466e53704ab6.
Report an issue: GitHub.