{"record":{"id":"db781bedfa0cf997","repo":"calesthio/OpenMontage","slug":"uploaded-video-did-not-finish-processing-in-time","errorCode":null,"errorMessage":"Uploaded video did not finish processing in time","messagePattern":"Uploaded video did not finish processing in time","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"error","filePath":"tools/video/gemini_omni_video.py","lineNumber":265,"sourceCode":"\n        upload_resp = requests_mod.post(\n            upload_url,\n            headers={\n                \"X-Goog-Upload-Command\": \"upload, finalize\",\n                \"X-Goog-Upload-Offset\": \"0\",\n                \"Content-Length\": str(len(video_bytes)),\n            },\n            data=video_bytes,\n            timeout=300,\n        )\n        upload_resp.raise_for_status()\n        file_info = upload_resp.json().get(\"file\", {})\n\n        # Wait until the uploaded video is processed before referencing it.\n        deadline = time.time() + _MAX_POLL_SECONDS\n        while str(file_info.get(\"state\", \"\")).upper() == \"PROCESSING\":\n            if time.time() > deadline:\n                raise TimeoutError(\"Uploaded video did not finish processing in time\")\n            time.sleep(_POLL_INTERVAL_SECONDS)\n            status_resp = requests_mod.get(\n                f\"{_BASE_URL}/{file_info.get('name')}\",\n                headers={\"x-goog-api-key\": api_key},\n                timeout=15,\n            )\n            status_resp.raise_for_status()\n            file_info = status_resp.json()\n        if str(file_info.get(\"state\", \"\")).upper() == \"FAILED\":\n            raise RuntimeError(\"Files API failed to process the uploaded video\")\n\n        uri = file_info.get(\"uri\")\n        if not uri:\n            raise RuntimeError(f\"Files API response missing uri: {file_info}\")\n        return uri\n\n    @staticmethod\n    def _extract_output_video(data: dict[str, Any]) -> dict[str, Any] | None:","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/video/gemini_omni_video.py#L247-L283","documentation":"Raised when an uploaded reference video stays in the Google Files API 'PROCESSING' state longer than _MAX_POLL_SECONDS. The tool uploads video bytes to the Files API and must wait until the file becomes ACTIVE before it can be referenced in a Gemini Omni generation request. If the server-side processing pipeline does not finish within the internal deadline, a TimeoutError aborts the wait.","triggerScenarios":"Calling gemini_omni_video with a video reference (uploaded via _upload_video): the initial upload succeeds (upload_resp 200), but every subsequent GET {file.name} status check keeps returning state=PROCESSING past the deadline computed from _MAX_POLL_SECONDS.","commonSituations":"Large or long reference videos (hundreds of MB) that Google takes minutes to transcode; transient Google-side processing slowdowns; uploading unusual codecs/container formats that stall server-side processing; tight _MAX_POLL_SECONDS defaults combined with big payloads.","solutions":["Retry the call — Files API processing latency is often transient and a second attempt finishes in time.","Reduce the input video size/duration (compress or trim) before uploading so server-side processing completes faster.","Re-encode the video to a mainstream codec/container (e.g. H.264 MP4) that the Files API processes quickly.","Increase _MAX_POLL_SECONDS in tools/video/gemini_omni_video.py if your workload regularly uses large references.","Check Google Cloud status for Gemini API/Files API incidents if uploads consistently stall."],"exampleFix":"// before\ninput.mp4  # 500MB 10-minute reference video, stalls in PROCESSING\n\n// after (shell)\nffmpeg -i input.mp4 -t 15 -c:v libx264 -crf 28 -vf scale=1280:-2 input_small.mp4\n# then pass input_small.mp4 as the video reference","handlingStrategy":"retry","validationCode":"from pathlib import Path\nimport subprocess\n\ndef precheck_reference(path: str, max_mb: int = 100) -> None:\n    p = Path(path)\n    if not p.is_file():\n        raise FileNotFoundError(path)\n    if p.stat().st_size > max_mb * 1024 * 1024:\n        raise ValueError(f\"{path} is {p.stat().st_size // (1024*1024)}MB; compress before upload\")\n    # verify the container is readable so Files API processing won't stall\n    subprocess.run([\"ffprobe\", \"-v\", \"error\", str(p)], check=True)","typeGuard":null,"tryCatchPattern":"try:\n    result = gemini_omni_video(inputs)\nexcept TimeoutError as e:\n    if \"finish processing\" in str(e):\n        # transient: shrink input or retry with backoff\n        raise RetryableError(\"files-api processing slow\") from e\n    raise","preventionTips":["Compress reference videos to H.264 MP4 under ~100MB before passing them in.","Trim references to the shortest useful duration.","Budget wall-clock for _MAX_POLL_SECONDS plus upload time when scheduling dependent stages."],"tags":["gemini","files-api","timeout","video-upload","polling","network"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}