sgl-project/sglang · error · ValueError

No frames decoded from video

Error message

No frames decoded from video: {video_path!r}

What it means

For V2V requests, Cosmos3 decodes the conditioning video with load_video; if decoding yields zero frames (corrupt file, unsupported codec, unreadable path), the stage cannot build condition latents and raises with the offending path.

Solutions

  1. Verify the file plays locally and inspect it (ffprobe video.mp4) — confirm codec/container support and nonzero duration
  2. Re-download or re-encode the video (ffmpeg -i in.mp4 -c:v libx264 out.mp4)
  3. Check the path/URL is readable from the server process and ffmpeg is installed
  4. Add a pre-upload probe in your client that rejects videos with 0 frames

Example fix

# before
req = {"video_path": "corrupt.mp4", "prompt": "..."}
# after
# re-encode to a supported codec first
# ffmpeg -i corrupt.mp4 -c:v libx264 -pix_fmt yuv420p fixed.mp4
req = {"video_path": "fixed.mp4", "prompt": "..."}
Defensive patterns

Strategy: validation

Validate before calling

import decord, os
assert os.path.exists(video_path) and os.path.getsize(video_path) > 0
vr = decord.VideoReader(video_path)
assert len(vr) > 0, "video has no frames"

Try / catch

catch ValueError matching 'No frames decoded' and route the item to a re-encode/reject path instead of retrying

Prevention

When it happens

Trigger: video_path is a non-empty string but load_video(video_path) returns an empty list — corrupt/truncated video, wrong container/codec, missing ffmpeg/dec support, or a URL/path the loader can't open.

Common situations: Downloading a partially-written mp4; feeding .avi/.webm the decode stack doesn't support; containerized deployment without ffmpeg; wrong mount path so the file is empty.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/99d7a89c8e419594. Report an issue: GitHub.

Appendix: source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/cosmos3.py:201

            )
            if not image_sources:
                raise ValueError("Cosmos3 I2V image list is empty")
            tensors: list[torch.Tensor] = []
            for src in image_sources:
                image = load_image(src)
                image = _resize_crop_pil(image, target_w, target_h)
                tensors.append(_pil_to_normalized_tensor(image))
            batch.preprocessed_image = torch.stack(tensors, dim=0).contiguous()
            self.log_info(
                f"Preprocessed {len(tensors)} conditioning image(s) to "
                f"{target_w}x{target_h}"
            )
            return batch

        if isinstance(video_path, str) and video_path:
            frames = load_video(video_path)
            if not frames:
                raise ValueError(f"No frames decoded from video: {video_path!r}")

            keep = (
                getattr(batch.sampling_params, "condition_video_keep", "first")
                or "first"
            )
            if keep not in ("first", "last"):
                raise ValueError(
                    f"condition_video_keep must be 'first' or 'last', got {keep!r}"
                )
            cond_indexes = self._resolve_condition_indexes(batch)
            # Encode the full output-length video so that the latent positions
            # we lock match what the decoder will reconstruct at those frame
            # indices. Encoding only the first ``max_idx*4+1`` frames produces
            # an out-of-distribution latent for the locked slots and decodes
            # to noise.
            num_source_frames = max(cond_indexes) * 4 + 1
            num_target_frames = batch.num_frames
            if keep == "last":

View on GitHub (pinned to 0132848349)