{"record":{"id":"d014f7a3b152aa36","repo":"BerriAI/litellm","slug":"failed-to-extract-video-data-e","errorCode":null,"errorMessage":"Failed to extract video data: {e}","messagePattern":"Failed to extract video data: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/vertex_ai/videos/transformation.py","lineNumber":570,"sourceCode":"            video_response: Final = response_data.get(\"response\", {})\n            videos: Final = video_response.get(\"videos\", [])\n\n            if not videos or len(videos) == 0:\n                raise ValueError(\"No video data found in completed operation\")\n\n            # Get the first video\n            video_data: Final = videos[0]\n            base64_encoded: Final = video_data.get(\"bytesBase64Encoded\")\n\n            if not base64_encoded:\n                raise ValueError(\"No base64 encoded video data found\")\n\n            # Decode base64 to bytes\n            video_bytes: Final = base64.b64decode(base64_encoded)\n            return video_bytes\n\n        except (KeyError, IndexError) as e:\n            raise ValueError(f\"Failed to extract video data: {e}\")\n\n    def transform_video_remix_request(\n        self,\n        video_id: str,\n        prompt: str,\n        api_base: str,\n        litellm_params: GenericLiteLLMParams,\n        headers: dict,\n        extra_body: dict[str, object] | None = None,\n    ) -> tuple[str, dict]:\n        \"\"\"\n        Video remix is not supported by Veo API.\n        \"\"\"\n        raise NotImplementedError(\n            \"Video remix is not supported by Vertex AI Veo. Please use video_generation() to create new videos.\"\n        )\n\n    def transform_video_remix_response(","sourceCodeStart":552,"sourceCodeEnd":588,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/vertex_ai/videos/transformation.py#L552-L588","documentation":"Thrown by the Vertex AI Veo video transformation while extracting generated video bytes from a completed operation response. The code indexes videos[0] inside a try block and converts KeyError/IndexError into this ValueError, meaning the response JSON lacked the 'videos' key or the list was empty. The '{e}' part names the original missing key (e.g. KeyError: 'videos'). It signals that the operation payload does not match the expected generateVideoResponse shape.","triggerScenarios":"Calling litellm.video_generation / video_status_retrieve with a vertex_ai/veo model where the polled operation response has no 'videos' array: polling before the operation is done, an operation that completed with an error instead of output, or a truncated/modified API response.","commonSituations":"Polling a Veo predictLongRunning operation too early; generation finished with 'error' instead of 'response.videos'; Google changing/renaming response fields; testing against recorded/mocked responses missing the videos field.","solutions":["Only transform the response after the operation has done=True and contains a 'response' object","Print/inspect the raw operation JSON to see whether 'videos' exists or an 'error' field is present instead","If the operation carries an error, surface it and retry generation rather than parsing for videos","Check for Vertex AI API shape changes if the same code worked on an older response capture"],"exampleFix":"# before\nvideo = litellm.video_status_retrieve(video_id=vid, custom_llm_provider=\"vertex_ai\")\nbytes_data = video.data[0]  # crashes downstream when videos missing\n\n# after\nop = fetch_raw_operation(vid)\nif not op.get(\"done\") or \"videos\" not in op.get(\"response\", {}):\n    raise RuntimeError(f\"Veo operation not ready or errored: {op}\")\nvideo = litellm.video_status_retrieve(video_id=vid, custom_llm_provider=\"vertex_ai\")","handlingStrategy":"validation","validationCode":"def veo_response_has_videos(operation: dict) -> bool:\n    return (\n        operation.get(\"done\") is True\n        and isinstance(operation.get(\"response\"), dict)\n        and isinstance(operation[\"response\"].get(\"videos\"), list)\n        and len(operation[\"response\"][\"videos\"]) > 0\n    )\n\nif not veo_response_has_videos(op):\n    raise RuntimeError(f\"Veo operation has no videos yet: {op.get('error', op)}\")","typeGuard":"from typing import TypedDict\n\nclass VeoVideo(TypedDict):\n    bytesBase64Encoded: str\n    mimeType: str\n\ndef is_veo_video_list(value: object) -> bool:\n    return (\n        isinstance(value, list)\n        and len(value) > 0\n        and isinstance(value[0], dict)\n        and \"bytesBase64Encoded\" in value[0]\n    )","tryCatchPattern":"try:\n    video = litellm.video_status_retrieve(video_id=vid, custom_llm_provider=\"vertex_ai\")\nexcept ValueError as e:\n    if \"Failed to extract video data\" in str(e):\n        # response shape unexpected: log raw operation and treat as failed generation\n        raise RuntimeError(f\"Veo response missing videos: {e}\") from e\n    raise","preventionTips":["Only invoke the video transform after confirming the operation is done and contains response.videos","Keep the raw operation JSON alongside parsed results so shape errors are debuggable","Treat 'error' in the operation as a first-class branch before parsing videos"],"tags":["vertex-ai","veo","video-generation","response-parsing","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"}