BerriAI/litellm · error · ValueError

end_time is required, got=

Error message

end_time is required, got={end_time} of type {type(end_time)}

What it means

Same normalizer as the start_time check: StandardLoggingPayloadSetup.cleanup_timestamps() converts end_time (and completion_start_time) to epoch-second floats and accepts only datetime.datetime or float. Any other type for end_time - None, str, int such as int(time.time()) - raises this ValueError with the value and its type. completion_start_time alone is forgiving: invalid types fall back to end_time_float.

Solutions

  1. Pass float(time.time()) or a datetime.datetime for end_time
  2. Compute end_time unconditionally before the call (guard the None-on-early-exit path)
  3. Omit end_time and let litellm set it when the response returns
  4. Coerce at the boundary: end_time = float(end_time) if isinstance(end_time, (int, float)) and not isinstance(end_time, bool) else end_time.timestamp()

Example fix

# before
start, end = int(time.time()), int(time.time()) + 2
litellm.completion(model="gpt-4o", messages=m, start_time=start, end_time=end)  # ValueError on end_time

# after
start, end = time.time(), time.time() + 2  # floats
litellm.completion(model="gpt-4o", messages=m, start_time=start, end_time=end)
Defensive patterns

Strategy: type-guard

Validate before calling

from datetime import datetime

if end_time is not None and not isinstance(end_time, (datetime, float)):
    end_time = float(end_time)  # coerce ints; strings should fail loudly in your code first
litellm.completion(model="gpt-4o", messages=m, end_time=end_time)

Type guard

from datetime import datetime

def is_valid_timestamp(v: object) -> bool:
    return (isinstance(v, datetime) or isinstance(v, float)) and not isinstance(v, bool)

Try / catch

try:
    litellm.completion(..., end_time=end)
except ValueError as e:
    if "end_time is required" in str(e):
        end = float(end)
        litellm.completion(..., end_time=end)

Prevention

When it happens

Trigger: Calling litellm completion/embedding (or the logging payload setup) with end_time=int(time.time()), an ISO string, or None - e.g. a custom timer that never fired, or time.time_ns() used for the finish timestamp.

Common situations: Symmetric latency measurement code that casts both times to int; end_time computed conditionally and left None on early exits; serialized timestamps re-read as strings from queues/caches.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/08aa466e53704ab6. Report an issue: GitHub.

Appendix: source

Thrown at litellm/litellm_core_utils/litellm_logging.py:4733

            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 77b7c6c40c)