{"record":{"id":"2b363ad181bbb965","repo":"BerriAI/litellm","slug":"source-video-generation-is-not-complete-yet-check","errorCode":null,"errorMessage":"Source video generation is not complete yet. Check the video status before editing.","messagePattern":"Source video generation is not complete yet\\. Check the video status before editing\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"litellm/llms/vertex_ai/videos/transformation.py","lineNumber":696,"sourceCode":"        litellm_params: GenericLiteLLMParams,\n        headers: dict,\n        extra_body: dict[str, object] | None = None,\n        prefetched_source_data: dict[str, Any] | None = None,\n    ) -> tuple[str, dict]:\n        \"\"\"\n        Build a predictLongRunning edit request from the pre-fetched source video.\n\n        The actual fetchPredictOperation HTTP call is hoisted into the handler so\n        it can use the shared async/sync httpx client instead of blocking the loop.\n        \"\"\"\n        if prefetched_source_data is None:\n            raise ValueError(\n                \"prefetched_source_data is required for Vertex AI video edit. \"\n                \"Ensure get_video_edit_prefetch_params is called by the handler.\"\n            )\n\n        if not prefetched_source_data.get(\"done\", False):\n            raise ValueError(\"Source video generation is not complete yet. Check the video status before editing.\")\n\n        source_response: Final[_VeoOperationResponse] = prefetched_source_data.get(\"response\", {})\n        videos: Final = source_response.get(\"videos\", [])\n        if not videos:\n            raise ValueError(\"No videos found in the completed operation. Cannot edit.\")\n\n        source_video: Final = videos[0]\n        video_input: Final[dict[str, str]] = {}\n        if \"gcsUri\" in source_video:\n            video_input[\"gcsUri\"] = source_video[\"gcsUri\"]\n        elif \"bytesBase64Encoded\" in source_video:\n            video_input[\"bytesBase64Encoded\"] = source_video[\"bytesBase64Encoded\"]\n            video_input[\"mimeType\"] = source_video.get(\"mimeType\", \"video/mp4\")\n        else:\n            raise ValueError(\"Source video has neither gcsUri nor bytesBase64Encoded. Cannot edit.\")\n\n        operation_name: Final = extract_original_video_id(video_id)\n        model: Final = self.extract_model_from_operation_name(operation_name) or \"\"","sourceCodeStart":678,"sourceCodeEnd":714,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/vertex_ai/videos/transformation.py#L678-L714","documentation":"Raised by the Vertex edit request transform when the pre-fetched source operation JSON has done != True. Veo edits read the finished source video out of its predictLongRunning operation, so editing before generation completes has nothing to read and LiteLLM fails fast with this ValueError.","triggerScenarios":"Calling litellm.video_edit(video_id=<operation still running>, ...) — e.g. immediately after video_generation returns status='processing', or when polling of the source operation was skipped/short-circuited.","commonSituations":"Fire-and-forget pipelines that chain generate→edit without waiting; poll loops with too-short intervals or a bug that treats 'processing' as done; editing a video whose generation silently stalled.","solutions":["Poll litellm.video_status_retrieve(video_id=...) until status is completed before calling video_edit","Add a small delay/backoff between polls — Veo generation typically takes tens of seconds to minutes","If the operation never completes, inspect the raw operation for an error field and retry generation"],"exampleFix":"# before\nlitellm.video_edit(video_id=vid, prompt=\"add fireworks\", custom_llm_provider=\"vertex_ai\")\n\n# after\nwhile True:\n    st = litellm.video_status_retrieve(video_id=vid, custom_llm_provider=\"vertex_ai\")\n    if st.status == \"completed\":\n        break\n    if st.status == \"failed\":\n        raise RuntimeError(st.error)\n    time.sleep(10)\nlitellm.video_edit(video_id=vid, prompt=\"add fireworks\", custom_llm_provider=\"vertex_ai\")","handlingStrategy":"retry","validationCode":"def wait_for_veo_video(video_id: str, timeout_s: int = 600, interval_s: int = 10) -> None:\n    deadline = time.time() + timeout_s\n    while time.time() < deadline:\n        st = litellm.video_status_retrieve(video_id=video_id, custom_llm_provider=\"vertex_ai\")\n        if st.status == \"completed\":\n            return\n        if st.status == \"failed\":\n            raise RuntimeError(f\"veo generation failed: {getattr(st, 'error', None)}\")\n        time.sleep(interval_s)\n    raise TimeoutError(f\"video {video_id} not ready after {timeout_s}s\")","typeGuard":"def operation_is_done(operation: dict) -> bool:\n    return operation.get(\"done\") is True","tryCatchPattern":"for attempt in range(max_attempts):\n    try:\n        litellm.video_edit(video_id=vid, prompt=p, custom_llm_provider=\"vertex_ai\")\n        break\n    except ValueError as e:\n        if \"not complete yet\" not in str(e) or attempt == max_attempts - 1:\n            raise\n        time.sleep(poll_interval)","preventionTips":["Always poll the source operation to done=True before chaining an edit","Treat 'processing' as a first-class state in your video pipeline state machine","Set a generous timeout: Veo generation regularly takes minutes"],"tags":["vertex-ai","veo","video-edit","async-operation","polling"],"backgroundTag":"async-operation-not-ready","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}