{"record":{"id":"08aa466e53704ab6","repo":"BerriAI/litellm","slug":"end-time-is-required-got-end-time-of-type-type","errorCode":null,"errorMessage":"end_time is required, got={end_time} of type {type(end_time)}","messagePattern":"end_time is required, got=(.+?) of type (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/litellm_logging.py","lineNumber":4727,"sourceCode":"            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\n    def append_system_prompt_messages(kwargs: dict | None = None, messages: Any | None = None):\n        \"\"\"\n        Append system prompt messages to the messages\n        \"\"\"\n        if kwargs is not None:\n            if kwargs.get(\"system\") is not None and isinstance(kwargs.get(\"system\"), str):\n                if messages is None:","sourceCodeStart":4709,"sourceCodeEnd":4745,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/litellm_logging.py#L4709-L4745","documentation":"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.","triggerScenarios":"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.","commonSituations":"Custom callbacks computing durations with integer arithmetic; JSON round-tripping turning datetimes into strings; failure handlers where end_time was never set before logging.","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"],"exampleFix":"# before\nend_time = int(time.time())  # ValueError: end_time is required\n\n# after\nend_time = float(time.time())\n# or\nend_time = datetime.datetime.now(datetime.timezone.utc)","handlingStrategy":"type-guard","validationCode":"import datetime\n\ndef safe_end_time(t, fallback=None):\n    if isinstance(t, datetime.datetime) or isinstance(t, float):\n        return t\n    return fallback if fallback is not None else datetime.datetime.now()","typeGuard":"import datetime\n\ndef is_valid_time_value(t) -> bool:\n    return isinstance(t, datetime.datetime) or isinstance(t, float)","tryCatchPattern":null,"preventionTips":["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"],"tags":["litellm","logging","type-validation","timestamps","callbacks"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}