{"record":{"id":"7934858b4004bb71","repo":"sgl-project/sglang","slug":"video-file-is-corrupted-or-cannot-be-decoded","errorCode":null,"errorMessage":"Video file is corrupted or cannot be decoded","messagePattern":"Video file is corrupted or cannot be decoded","errorType":"http","errorClass":"HTTPException","httpStatus":432,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/mimo_v2.py","lineNumber":1670,"sourceCode":"        ).build(_processor)\n\n    @property\n    def spatial_merge_size(self):\n        return self.vision_config.spatial_merge_size\n\n    def _preprocess_video_sync(self, vdw, preprocess_kwargs=None):\n        # Seed with processor_config defaults so E/D agree on fps/min/max.\n        default_kwargs = {\n            k: v\n            for k, v in self.mimo_processor.default_video_processor_kwargs.items()\n            if v is not None and k in (\"fps\", \"min_frames\", \"max_frames\", \"num_frames\")\n        }\n        ele = {**default_kwargs, **(preprocess_kwargs or {})}\n        try:\n            return _decode_frames_and_timestamps(vdw, ele)\n        except Exception as e:\n            logger.error(f\"Video decode failed in _preprocess_video_sync: {e}\")\n            raise HTTPException(\n                status_code=432, detail=\"Video file is corrupted or cannot be decoded\"\n            )\n\n    def process_mm_data(\n        self, input_text, images=None, videos=None, audios=None, **kwargs\n    ) -> dict:\n        if audios and not self.AUDIO_TOKEN_REGEX.search(input_text or \"\"):\n            input_text = f\"{self.mm_tokens.audio_token}{input_text or ''}\"\n\n        processed_images = []\n        processed_videos = []\n        processed_audios = []\n\n        if images:\n            processed_images = list(images)\n\n        if videos:\n            for video in videos:","sourceCodeStart":1652,"sourceCodeEnd":1688,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/mimo_v2.py#L1652-L1688","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: url returns HTML error page → HTTP 432\nvideo = {'url': expired_presigned_url}\n# after\nvideo = {'url': fresh_presigned_url}  # curl -I shows 200 + video/mp4","handlingStrategy":"try-catch","validationCode":"import subprocess\ndef video_ok(path_or_url):\n    try:\n        subprocess.run(['ffprobe', '-v','error', path_or_url], check=True, timeout=30,\n                       stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n        return True\n    except Exception:\n        return False\n\nassert video_ok(url), 'video not decodable; refusing to send'","typeGuard":null,"tryCatchPattern":"try:\n    out = await client.generate(prompt, video=url)\nexcept HTTPException as e:  # sglang client maps 432\n    if e.status_code == 432:\n        re_upload_and_retry(url)  # re-fetch source, verify with ffprobe, retry once\n    else:\n        raise","preventionTips":["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"],"tags":["video","decode","http-exception","corrupt-file"],"backgroundTag":"media-decode-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}