{"record":{"id":"eb453659d804f93d","repo":"BerriAI/litellm","slug":"no-videos-found-in-the-completed-operation-cannot","errorCode":null,"errorMessage":"No videos found in the completed operation. Cannot edit.","messagePattern":"No videos found in the completed operation\\. Cannot edit\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/vertex_ai/videos/transformation.py","lineNumber":701,"sourceCode":"        \"\"\"\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 \"\"\n\n        instance_dict: Final[dict[str, object]] = {\"prompt\": prompt, \"video\": video_input}\n        request_data: Final[dict[str, object]] = {\"instances\": [instance_dict]}\n\n        if extra_body:","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/vertex_ai/videos/transformation.py#L683-L719","documentation":"Raised by the Vertex edit request transform when the source operation is marked done=True but its response contains no 'videos' array. Veo operations can complete with an error or an empty result instead of generated video, and there is nothing to edit in that case, so LiteLLM raises this ValueError.","triggerScenarios":"Editing a video whose predictLongRunning operation finished with an error (e.g. safety filter rejection, quota) — done is true but response.videos is empty or missing.","commonSituations":"Prompts rejected by Veo safety filters; generation failing after the poll loop saw done=True; API responses where error replaces response.videos.","solutions":["Inspect the raw operation JSON (prefetch it yourself via get_video_edit_prefetch_params) and look for an 'error' object","If generation errored, fix the prompt/parameters and regenerate the source video before editing","Treat this as a terminal failure of the source video — do not retry the edit"],"exampleFix":"# before\nlitellm.video_edit(video_id=vid, prompt=\"...\", custom_llm_provider=\"vertex_ai\")\n\n# after\np_url, _ = config.get_video_edit_prefetch_params(vid, api_base, litellm_params, headers)\nop = httpx.get(p_url, headers=headers).json()\nif op.get(\"done\") and not op.get(\"response\", {}).get(\"videos\"):\n    raise RuntimeError(f\"source generation failed: {op.get('error', 'no videos')}\")\nlitellm.video_edit(video_id=vid, prompt=\"...\", custom_llm_provider=\"vertex_ai\")","handlingStrategy":"try-catch","validationCode":"def operation_has_videos(operation: dict) -> bool:\n    return bool(operation.get(\"done\")) and bool(operation.get(\"response\", {}).get(\"videos\"))","typeGuard":"def completed_with_videos(operation: dict) -> bool:\n    resp = operation.get(\"response\")\n    return operation.get(\"done\") is True and isinstance(resp, dict) and len(resp.get(\"videos\", [])) > 0","tryCatchPattern":"try:\n    litellm.video_edit(video_id=vid, prompt=p, custom_llm_provider=\"vertex_ai\")\nexcept ValueError as e:\n    if \"No videos found in the completed operation\" in str(e):\n        # source generation finished with an error: regenerate, do not retry the edit\n        raise SourceGenerationFailed(vid) from e\n    raise","preventionTips":["Before editing, prefetch the operation and verify done AND response.videos non-empty","Check the operation's error field whenever done=True but no videos are present","Keep raw operation JSON for post-mortems on failed generations"],"tags":["vertex-ai","veo","video-edit","generation-failed","valueerror"],"backgroundTag":"missing-response-field","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}