{"record":{"id":"0475238207ccb2c5","repo":"BerriAI/litellm","slug":"start-time-utc-and-end-time-utc-must-be-provided-t","errorCode":null,"errorMessage":"start_time_utc and end_time_utc must be provided together","messagePattern":"start_time_utc and end_time_utc must be provided together","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/integrations/focus/focus_logger.py","lineNumber":92,"sourceCode":"            )\n        return self._engine\n\n    async def export_usage_data(\n        self,\n        *,\n        limit: int | None = None,\n        start_time_utc: datetime | None = None,\n        end_time_utc: datetime | None = None,\n    ) -> None:\n        \"\"\"Public hook to trigger export immediately.\n\n        When called without time bounds (manual /vantage/export with no\n        start/end), exports **all** available data instead of the last\n        scheduled window.  The hourly/daily window only applies to\n        automatic scheduler runs.\n        \"\"\"\n        if bool(start_time_utc) ^ bool(end_time_utc):\n            raise ValueError(\"start_time_utc and end_time_utc must be provided together\")\n\n        if start_time_utc and end_time_utc:\n            window: Final = FocusTimeWindow(\n                start_time=start_time_utc,\n                end_time=end_time_utc,\n                frequency=self.frequency,\n            )\n            await self._export_window(window=window, limit=limit)\n        else:\n            # No time bounds → export all available data\n            await self._export_all(limit=limit)\n\n    async def dry_run_export_usage_data(self, limit: int | None = DEFAULT_DRY_RUN_LIMIT) -> dict[str, Any]:\n        \"\"\"Return transformed data without uploading.\"\"\"\n        engine: Final = self._ensure_engine()\n        return await engine.dry_run_export_usage_data(limit=limit)\n\n    async def initialize_focus_export_job(self) -> None:","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/integrations/focus/focus_logger.py#L74-L110","documentation":"FocusLogger.export_usage_data raises ValueError when exactly one of start_time_utc / end_time_utc is passed. Time bounds only make sense as a pair (they become the FocusTimeWindow); the check is a boolean XOR, so passing either bound alone is rejected before any DB/export work happens.","triggerScenarios":"Calling export_usage_data(start_time_utc=ts) or export_usage_data(end_time_utc=ts) with the other bound omitted — e.g. a caller forwarding optional query params from an HTTP endpoint where only one was supplied.","commonSituations":"REST handler mapping optional start/end query params straight into the call; a client sending only 'since'; datetime parsed as falsy on one side (note: datetime.min-like values are fine, but None defaults trip it).","solutions":["Pass both bounds together: export_usage_data(start_time_utc=start, end_time_utc=end).","Or pass neither to export all available data.","In HTTP handlers, default missing params so both are None or both are set (validate at the request boundary)."],"exampleFix":"# before\nawait logger.export_usage_data(start_time_utc=start)\n\n# after\nif start and end:\n    await logger.export_usage_data(start_time_utc=start, end_time_utc=end)\nelse:\n    await logger.export_usage_data()  # export all","handlingStrategy":"validation","validationCode":"if (start_time_utc is None) != (end_time_utc is None):\n    raise ValueError(\"Provide both start_time_utc and end_time_utc, or neither\")\nawait logger.export_usage_data(limit=limit, start_time_utc=start_time_utc, end_time_utc=end_time_utc)","typeGuard":"def is_valid_window(start: datetime | None, end: datetime | None) -> bool:\n    return (start is None) == (end is None)","tryCatchPattern":null,"preventionTips":["Validate optional start/end pairs at the HTTP boundary before calling export APIs.","In request handlers, treat a missing bound as 'export all' explicitly rather than forwarding partial bounds.","Add a unit test covering (start-only), (end-only), (both), (neither)."],"tags":["validation","focus-export","api-misuse","time-window"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}