sgl-project/sglang · error · HTTPException
Video file is corrupted or cannot be decoded
Error message
Video file is corrupted or cannot be decoded
What it means
An HTTPException (status 432, a custom code) raised by _preprocess_video_sync when _decode_frames_and_timestamps raises any exception during video decoding. It converts arbitrary decode failures (corrupt container, unsupported codec, truncated file) into a client-facing 'video is corrupted' response.
Source
Thrown at python/sglang/srt/multimodal/processors/mimo_v2.py:1670
).build(_processor)
@property
def spatial_merge_size(self):
return self.vision_config.spatial_merge_size
def _preprocess_video_sync(self, vdw, preprocess_kwargs=None):
# Seed with processor_config defaults so E/D agree on fps/min/max.
default_kwargs = {
k: v
for k, v in self.mimo_processor.default_video_processor_kwargs.items()
if v is not None and k in ("fps", "min_frames", "max_frames", "num_frames")
}
ele = {**default_kwargs, **(preprocess_kwargs or {})}
try:
return _decode_frames_and_timestamps(vdw, ele)
except Exception as e:
logger.error(f"Video decode failed in _preprocess_video_sync: {e}")
raise HTTPException(
status_code=432, detail="Video file is corrupted or cannot be decoded"
)
def process_mm_data(
self, input_text, images=None, videos=None, audios=None, **kwargs
) -> dict:
if audios and not self.AUDIO_TOKEN_REGEX.search(input_text or ""):
input_text = f"{self.mm_tokens.audio_token}{input_text or ''}"
processed_images = []
processed_videos = []
processed_audios = []
if images:
processed_images = list(images)
if videos:
for video in videos:View on GitHub (pinned to 0132848349)
Solutions
- Verify the video plays and decodes locally (ffprobe file) before sending
- Re-fetch/re-upload the source file if the downloaded bytes are truncated or an error page
- Re-encode to a widely supported format (H.264 MP4) if codec support is the issue
- If using pre-signed URLs, ensure they are fresh and accessible from the server
Example fix
# before: url returns HTML error page → HTTP 432
video = {'url': expired_presigned_url}
# after
video = {'url': fresh_presigned_url} # curl -I shows 200 + video/mp4 Defensive patterns
Strategy: try-catch
Validate before calling
import subprocess
def video_ok(path_or_url):
try:
subprocess.run(['ffprobe', '-v','error', path_or_url], check=True, timeout=30,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except Exception:
return False
assert video_ok(url), 'video not decodable; refusing to send' Try / catch
try:
out = await client.generate(prompt, video=url)
except HTTPException as e: # sglang client maps 432
if e.status_code == 432:
re_upload_and_retry(url) # re-fetch source, verify with ffprobe, retry once
else:
raise Prevention
- ffprobe every user-uploaded video before storing it
- Re-encode exotic codecs to H.264 MP4 at ingest
- Use fresh pre-signed URLs; check content-type is video/* not text/html
When it happens
Trigger: Sending a request whose video URL/bytes cannot be decoded by VideoDecoderWrapper — truncated download, non-video file, unsupported codec/container, or an unreadable URL — on the async path process_mm_data_async.
Common situations: Expired/invalid pre-signed URLs returning an HTML error page instead of video; partially uploaded files; exotic codecs (e.g. AV1/HEVC builds without support); network hiccups truncating the body.
Related errors
- Multimodal data is corrupted or cannot be decoded: {e}
- Could not decode video: {e}
- `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.
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/7934858b4004bb71.
Report an issue: GitHub.