BerriAI/litellm · error · ValueError

start_time is required, got={start_time} of type {type(start

Error message

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

What it means

LiteLLM's logging time-normalization helper accepts only datetime.datetime or float for start_time. Anything else (None, int, ISO string, pandas.Timestamp) hits the else branch and raises this ValueError. Note int is rejected: isinstance(3, float) is False in Python, so integer timestamps fail.

Source

Thrown at litellm/litellm_core_utils/litellm_logging.py:4720

    ) -> tuple[float, float, float]:
        """
        Convert datetime objects to floats

        Args:
            start_time: Union[dt_object, float]
            end_time: Union[dt_object, float]
            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

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass datetime.datetime objects (preferred): start_time=datetime.datetime.now()
  2. If using epoch numbers, ensure they are floats: float(time.time())
  3. Default Optional values before calling: start_time or datetime.datetime.now()
  4. Parse ISO strings first: datetime.datetime.fromisoformat(s)

Example fix

# before
import time
start_time = int(time.time())  # int -> ValueError

# after
import time, datetime
start_time = time.time()          # float, ok
# or better:
start_time = datetime.datetime.now(datetime.timezone.utc)
Defensive patterns

Strategy: type-guard

Validate before calling

import datetime, time

def normalize_start_time(t):
    if isinstance(t, datetime.datetime):
        return t
    if isinstance(t, (int, float)) and not isinstance(t, bool):
        return datetime.datetime.fromtimestamp(float(t))
    raise TypeError(f'start_time must be datetime or float, got {type(t)}')

Type guard

import datetime

def is_valid_time_value(t) -> bool:
    return isinstance(t, datetime.datetime) or isinstance(t, float)  # note: int is NOT accepted

Try / catch

try:
    logging_obj.some_log_call(start_time=start_time, end_time=end_time)
except ValueError as e:
    if 'start_time is required' in str(e):
        logging.error('bad start_time type: %r', start_time)
        raise
    raise

Prevention

When it happens

Trigger: Calling logging APIs that funnel into this helper — e.g. custom success/failure handlers or mock/callback code passing start_time as int(time.time()), a string timestamp, or None (e.g. when a streaming chunk lacks timing and None is forwarded).

Common situations: Custom callbacks or test harnesses passing int timestamps (a very common trap since ints look numeric); datetime stored/retrieved from JSON as ISO strings; Optional[datetime] values forwarded without a default.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/7d014fd507e4c89f. Report an issue: GitHub.