BerriAI/litellm · error · ValueError

No base64 encoded video data found

Error message

No base64 encoded video data found

What it means

The deepest extraction step of the Veo download transformer: the videos array exists and the first element was read, but it has no `bytesBase64Encoded` field, so there is nothing to base64-decode into video bytes. Like the empty-videos case, this means the operation completed but returned a video entry in an unexpected shape — commonly a GCS reference (gcsUri) instead of inline base64, or a filtered/empty entry.

Source

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

        if not response_data.get("done", False):
            raise ValueError(
                "Video generation is not complete yet. Please check status with video_status() before downloading."
            )

        try:
            video_response: Final = response_data.get("response", {})
            videos: Final = video_response.get("videos", [])

            if not videos or len(videos) == 0:
                raise ValueError("No video data found in completed operation")

            # Get the first video
            video_data: Final = videos[0]
            base64_encoded: Final = video_data.get("bytesBase64Encoded")

            if not base64_encoded:
                raise ValueError("No base64 encoded video data found")

            # Decode base64 to bytes
            video_bytes: Final = base64.b64decode(base64_encoded)
            return video_bytes

        except (KeyError, IndexError) as e:
            raise ValueError(f"Failed to extract video data: {e}")

    def transform_video_remix_request(
        self,
        video_id: str,
        prompt: str,
        api_base: str,
        litellm_params: GenericLiteLLMParams,
        headers: dict,
        extra_body: dict[str, object] | None = None,
    ) -> tuple[str, dict]:
        """

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Inspect videos[0] (log the status response) — if it carries gcsUri, download from GCS directly (gsutil/storage client) using your project credentials.
  2. Retry with shorter durations or lower resolution to get inline base64 payloads.
  3. Re-run the generation if the entry looks filtered/empty (no gcsUri either) after adjusting the prompt.
  4. Upgrade litellm — newer builds handle gcsUri-style Veo responses.
Defensive patterns

Strategy: fallback

Type guard

def video_entry_has_inline_bytes(entry: dict) -> bool:
    return isinstance(entry.get("bytesBase64Encoded"), str) and len(entry["bytesBase64Encoded"]) > 0

Try / catch

try:
    content = litellm.retrieve_video_content(video_id=vid, vertex_project=proj)
except ValueError as e:
    if "No base64 encoded video data" in str(e):
        st = litellm.video_status(video_id=vid, vertex_project=proj)
        gcs = (((st.status_response or {}).get("response", {}) or {}).get("videos", [{}])[0]).get("gcsUri")
        if gcs:
            content = download_from_gcs(gcs)  # fallback path for GCS-stored results
        else:
            raise
    else:
        raise

Prevention

When it happens

Trigger: A completed Veo operation whose videos[0] contains {"gcsUri": "gs://..."} or an error note instead of inline base64 data; large videos where Vertex stores output in GCS rather than embedding bytes.

Common situations: Long/high-resolution generations exceeding the inline-payload size so results land in GCS; model/region variants with GCS-only responses; safety-filtered entries with no payload.

Related errors


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