BerriAI/litellm · error · ValueError

No videos found in the completed operation. Cannot edit.

Error message

No videos found in the completed operation. Cannot edit.

What it means

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.

Source

Thrown at litellm/llms/vertex_ai/videos/transformation.py:701

        """
        Build a predictLongRunning edit request from the pre-fetched source video.

        The actual fetchPredictOperation HTTP call is hoisted into the handler so
        it can use the shared async/sync httpx client instead of blocking the loop.
        """
        if prefetched_source_data is None:
            raise ValueError(
                "prefetched_source_data is required for Vertex AI video edit. "
                "Ensure get_video_edit_prefetch_params is called by the handler."
            )

        if not prefetched_source_data.get("done", False):
            raise ValueError("Source video generation is not complete yet. Check the video status before editing.")

        source_response: Final[_VeoOperationResponse] = prefetched_source_data.get("response", {})
        videos: Final = source_response.get("videos", [])
        if not videos:
            raise ValueError("No videos found in the completed operation. Cannot edit.")

        source_video: Final = videos[0]
        video_input: Final[dict[str, str]] = {}
        if "gcsUri" in source_video:
            video_input["gcsUri"] = source_video["gcsUri"]
        elif "bytesBase64Encoded" in source_video:
            video_input["bytesBase64Encoded"] = source_video["bytesBase64Encoded"]
            video_input["mimeType"] = source_video.get("mimeType", "video/mp4")
        else:
            raise ValueError("Source video has neither gcsUri nor bytesBase64Encoded. Cannot edit.")

        operation_name: Final = extract_original_video_id(video_id)
        model: Final = self.extract_model_from_operation_name(operation_name) or ""

        instance_dict: Final[dict[str, object]] = {"prompt": prompt, "video": video_input}
        request_data: Final[dict[str, object]] = {"instances": [instance_dict]}

        if extra_body:

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Inspect the raw operation JSON (prefetch it yourself via get_video_edit_prefetch_params) and look for an 'error' object
  2. If generation errored, fix the prompt/parameters and regenerate the source video before editing
  3. Treat this as a terminal failure of the source video — do not retry the edit

Example fix

# before
litellm.video_edit(video_id=vid, prompt="...", custom_llm_provider="vertex_ai")

# after
p_url, _ = config.get_video_edit_prefetch_params(vid, api_base, litellm_params, headers)
op = httpx.get(p_url, headers=headers).json()
if op.get("done") and not op.get("response", {}).get("videos"):
    raise RuntimeError(f"source generation failed: {op.get('error', 'no videos')}")
litellm.video_edit(video_id=vid, prompt="...", custom_llm_provider="vertex_ai")
Defensive patterns

Strategy: try-catch

Validate before calling

def operation_has_videos(operation: dict) -> bool:
    return bool(operation.get("done")) and bool(operation.get("response", {}).get("videos"))

Type guard

def completed_with_videos(operation: dict) -> bool:
    resp = operation.get("response")
    return operation.get("done") is True and isinstance(resp, dict) and len(resp.get("videos", [])) > 0

Try / catch

try:
    litellm.video_edit(video_id=vid, prompt=p, custom_llm_provider="vertex_ai")
except ValueError as e:
    if "No videos found in the completed operation" in str(e):
        # source generation finished with an error: regenerate, do not retry the edit
        raise SourceGenerationFailed(vid) from e
    raise

Prevention

When it happens

Trigger: 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.

Common situations: Prompts rejected by Veo safety filters; generation failing after the poll loop saw done=True; API responses where error replaces response.videos.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/eb453659d804f93d. Report an issue: GitHub.