{"record":{"id":"7fc38543c32f4cbf","repo":"BerriAI/litellm","slug":"prefetched-source-data-is-required-for-vertex-ai-v","errorCode":null,"errorMessage":"prefetched_source_data is required for Vertex AI video edit. Ensure get_video_edit_prefetch_params is called by the handler.","messagePattern":"prefetched_source_data is required for Vertex AI video edit\\. Ensure get_video_edit_prefetch_params is called by the handler\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/vertex_ai/videos/transformation.py","lineNumber":690,"sourceCode":"\n    def transform_video_edit_request(\n        self,\n        prompt: str,\n        video_id: str,\n        api_base: str,\n        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\"]","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/vertex_ai/videos/transformation.py#L672-L708","documentation":"Raised by the Vertex edit request transform when prefetched_source_data is None. In normal operation the LiteLLM handler (litellm/llms/custom_httpx/llm_http_handler.py:7680) calls get_video_edit_prefetch_params, performs the fetchPredictOperation call, and passes the operation JSON back in. This ValueError therefore means the transform was invoked directly or via a code path that skipped the prefetch step.","triggerScenarios":"Calling config.transform_video_edit_request(...) manually in custom code; a forked/modified handler that builds the edit request without first fetching the source operation; provider interface changes where a handler forgets the prefetch contract.","commonSituations":"Writing a custom video handler that mimics litellm's; upgrading litellm versions where the handler/prefetch contract shifted; unit tests invoking the transformation in isolation.","solutions":["Use the standard litellm.video_edit(...) entry point so the handler performs the prefetch for you","If calling the transform directly, first call get_video_edit_prefetch_params, HTTP GET that URL, and pass response.json() as prefetched_source_data"],"exampleFix":"# before\nurl, body = config.transform_video_edit_request(video_id, prompt, api_base, litellm_params, headers)\n# ValueError: prefetched_source_data is required\n\n# after\np_url, p_body = config.get_video_edit_prefetch_params(video_id, api_base, litellm_params, headers)\nresp = httpx.get(p_url, headers=headers)  # fetchPredictOperation\nurl, body = config.transform_video_edit_request(\n    video_id, prompt, api_base, litellm_params, headers,\n    prefetched_source_data=resp.json(),\n)","handlingStrategy":"validation","validationCode":"def build_edit_request(config, video_id, prompt, api_base, litellm_params, headers, http_get):\n    p_url, _ = config.get_video_edit_prefetch_params(video_id, api_base, litellm_params, headers)\n    prefetched = http_get(p_url, headers).json()  # fetchPredictOperation\n    return config.transform_video_edit_request(\n        video_id, prompt, api_base, litellm_params, headers,\n        prefetched_source_data=prefetched,\n    )","typeGuard":"from typing import Any\n\ndef has_prefetched_source_data(kwargs: dict[str, Any]) -> bool:\n    return isinstance(kwargs.get(\"prefetched_source_data\"), dict)","tryCatchPattern":"try:\n    url, body = config.transform_video_edit_request(video_id, prompt, api_base, lp, headers, prefetched_source_data=prefetched)\nexcept ValueError as e:\n    if \"prefetched_source_data is required\" in str(e):\n        raise RuntimeError(\"handler bug: prefetch step was skipped\") from e\n    raise","preventionTips":["Prefer the public litellm.video_edit entry point over calling transformations directly","If invoking transforms manually, always pair get_video_edit_prefetch_params + HTTP fetch + pass the JSON back in","Assert prefetched_source_data is not None before calling the transform in custom handlers"],"tags":["vertex-ai","veo","video-edit","internal-contract","valueerror"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}