sgl-project/sglang · error · ValueError
Could not decode video: {e}
Error message
Could not decode video: {e} What it means
The video decoder wrapper (torchcodec or decord) raised an unexpected exception while opening/decoding the video source; it is rewrapped as ValueError because backends raise heterogeneous exception types (RuntimeError etc.). The chained 'from e' preserves the root cause.
Source
Thrown at python/sglang/srt/utils/common.py:1979
if isinstance(video_file, VideoData):
# preprocess_kwargs is consumed by the multimodal processor, not here.
video_file = video_file.url
if isinstance(video_file, (list, tuple, torch.Tensor, np.ndarray)):
return video_file
source = _normalize_video_input(video_file)
if source is None:
raise ValueError(f"Unsupported video input type: {type(video_file)}")
device = "cuda" if use_gpu else "cpu"
try:
return VideoDecoderWrapper(source, device=device)
except (ImportError, MemoryError):
raise # missing backend / OOM is not a bad payload
except Exception as e:
# Broad on purpose: torchcodec raises RuntimeError, decord its own type.
raise ValueError(f"Could not decode video: {e}") from e
def sample_video_frames(video, *, desired_fps: int, max_frames: int) -> list[int]:
total_frames = len(video)
assert total_frames > 0, "Video must have at least one frame"
avg_fps = video.avg_fps
duration = total_frames / avg_fps if avg_fps > 0 else 0
fps = min(desired_fps, avg_fps)
num_frames = math.floor(duration * fps)
num_frames = min(max_frames, num_frames, total_frames)
num_frames = max(1, num_frames) # At least one frame
if num_frames == total_frames:
return list(range(total_frames))
else:
return np.linspace(0, total_frames - 1, num_frames, dtype=int).tolist()
View on GitHub (pinned to 0132848349)
Solutions
- Inspect the chained original exception (__cause__) for the true backend error
- Verify the video opens with ffprobe or an external player; re-encode to H.264 MP4 if codec is exotic
- Ensure torchcodec/decord and ffmpeg are installed and versions are compatible
- Handle at the request layer and reject/report the bad payload instead of crashing the server
Example fix
// before
video = load_video(path) # crashes on corrupt file
// after
try:
video = load_video(path)
except ValueError as e:
raise HTTPException(400, f"bad video: {e}") from e Defensive patterns
Strategy: try-catch
Validate before calling
import subprocess subprocess.run(["ffprobe", "-v", "error", path], check=True) # cheap pre-check
Try / catch
try:
video = load_video(path)
except ValueError as e:
if "Could not decode" in str(e):
reject_payload(original=e.__cause__) Prevention
- Re-encode user uploads to H.264 MP4 before inference
- Always inspect e.__cause__ for the torchcodec/decord root error
- Install matching torchcodec + ffmpeg versions
When it happens
Trigger: Corrupt/truncated video file, unsupported codec/container, unreadable URL, or backend inconsistency — any non-ImportError/MemoryError from VideoDecoderWrapper construction.
Common situations: Users uploading broken or unusual-codec videos; partially downloaded files; decord/torchcodec version incompatibilities with certain codecs.
Related errors
- Video file is corrupted or cannot be decoded
- `mixed_qkv` must be a 2D tensor (got ndim={mixed_qkv.ndim}).
- `mixed_qkv` must be 2D (got ndim={mixed_qkv.ndim}).
- MXFP8 fused decode prologue requires head_dim-aligned Q/K/V.
- MXFP8 fused decode prologue requires K/V scale buffers.
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/62df5c8501e80e3a.
Report an issue: GitHub.