{"record":{"id":"7d014fd507e4c89f","repo":"BerriAI/litellm","slug":"start-time-is-required-got-start-time-of-type","errorCode":null,"errorMessage":"start_time is required, got={start_time} of type {type(start_time)}","messagePattern":"start_time is required, got=(.+?) of type (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/litellm_logging.py","lineNumber":4720,"sourceCode":"    ) -> tuple[float, float, float]:\n        \"\"\"\n        Convert datetime objects to floats\n\n        Args:\n            start_time: Union[dt_object, float]\n            end_time: Union[dt_object, float]\n            completion_start_time: Union[dt_object, float]\n\n        Returns:\n            Tuple[float, float, float]: A tuple containing the start time, end time, and completion start time as floats.\n        \"\"\"\n\n        if isinstance(start_time, datetime.datetime):\n            start_time_float = start_time.timestamp()\n        elif isinstance(start_time, float):\n            start_time_float = start_time\n        else:\n            raise ValueError(f\"start_time is required, got={start_time} of type {type(start_time)}\")\n\n        if isinstance(end_time, datetime.datetime):\n            end_time_float = end_time.timestamp()\n        elif isinstance(end_time, float):\n            end_time_float = end_time\n        else:\n            raise ValueError(f\"end_time is required, got={end_time} of type {type(end_time)}\")\n\n        if isinstance(completion_start_time, datetime.datetime):\n            completion_start_time_float = completion_start_time.timestamp()\n        elif isinstance(completion_start_time, float):\n            completion_start_time_float = completion_start_time\n        else:\n            completion_start_time_float = end_time_float\n\n        return start_time_float, end_time_float, completion_start_time_float\n\n    @staticmethod","sourceCodeStart":4702,"sourceCodeEnd":4738,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/litellm_logging.py#L4702-L4738","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Pass datetime.datetime objects (preferred): start_time=datetime.datetime.now()","If using epoch numbers, ensure they are floats: float(time.time())","Default Optional values before calling: start_time or datetime.datetime.now()","Parse ISO strings first: datetime.datetime.fromisoformat(s)"],"exampleFix":"# before\nimport time\nstart_time = int(time.time())  # int -> ValueError\n\n# after\nimport time, datetime\nstart_time = time.time()          # float, ok\n# or better:\nstart_time = datetime.datetime.now(datetime.timezone.utc)","handlingStrategy":"type-guard","validationCode":"import datetime, time\n\ndef normalize_start_time(t):\n    if isinstance(t, datetime.datetime):\n        return t\n    if isinstance(t, (int, float)) and not isinstance(t, bool):\n        return datetime.datetime.fromtimestamp(float(t))\n    raise TypeError(f'start_time must be datetime or float, got {type(t)}')","typeGuard":"import datetime\n\ndef is_valid_time_value(t) -> bool:\n    return isinstance(t, datetime.datetime) or isinstance(t, float)  # note: int is NOT accepted","tryCatchPattern":"try:\n    logging_obj.some_log_call(start_time=start_time, end_time=end_time)\nexcept ValueError as e:\n    if 'start_time is required' in str(e):\n        logging.error('bad start_time type: %r', start_time)\n        raise\n    raise","preventionTips":["Always construct timestamps with datetime.datetime.now() in custom handlers","Cast epoch values explicitly: float(time.time()) — ints are rejected","Default Optional timestamps before passing them into logging helpers"],"tags":["litellm","logging","type-validation","timestamps","callbacks"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}