{"record":{"id":"a6ba4fa4c74eec89","repo":"unslothai/unsloth","slug":"that-reference-video-decoded-to-no-frames","errorCode":null,"errorMessage":"That reference video decoded to no frames.","messagePattern":"That reference video decoded to no frames\\.","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/video_minimax_h3.py","lineNumber":419,"sourceCode":"                raise ValueError(\n                    f\"MiniMax-H3 reference videos run {H3_REF_VIDEO_MIN_SECONDS:g} to \"\n                    f\"{H3_REF_VIDEO_MAX_SECONDS:g} seconds; this one is longer than \"\n                    f\"{H3_REF_VIDEO_MAX_SECONDS:g}s. Trim it first.\"\n                )\n            target_source = int(next_target * source_fps / H3_FPS)\n            if target_source > source_index:\n                continue\n            image = frame.to_image().convert(\"RGB\")\n            if fitted_size is None:\n                fitted_size = h3_reference_frame_size(*image.size)\n            if image.size != fitted_size:\n                image = image.resize(fitted_size, Image.LANCZOS)\n            while int(next_target * source_fps / H3_FPS) <= source_index:\n                frames.append(image)\n                next_target += 1\n\n    if decoded_count == 0:\n        raise ValueError(\"That reference video decoded to no frames.\")\n    duration = decoded_count / source_fps\n    if duration + 1e-6 < H3_REF_VIDEO_MIN_SECONDS:\n        raise ValueError(\n            f\"MiniMax-H3 reference videos run {H3_REF_VIDEO_MIN_SECONDS:g} to \"\n            f\"{H3_REF_VIDEO_MAX_SECONDS:g} seconds; this one is {duration:.1f}s.\"\n        )\n    frames = frames[: int(round(duration * H3_FPS))]\n\n    waveform, sample_rate = (None, None)\n    with av.open(io.BytesIO(blob)) as container:\n        if container.streams.audio:\n            waveform, sample_rate = _decode_audio_stream(container, np)\n    return frames, waveform, sample_rate\n\n\ndef decode_h3_reference_audio(blob: bytes) -> tuple[Any, int]:\n    \"\"\"Decode one uploaded audio file to a float32 ``(samples, channels)`` waveform + its rate.\"\"\"\n    import io","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/video_minimax_h3.py#L401-L437","documentation":"After the decode loop over a reference video, decoded_count == 0 means PyAV iterated the container without yielding a single frame, so the code raises ValueError instead of dividing by source_fps on a phantom duration. This is separate from the no-video-track error (513): here the track exists but produces nothing, e.g. headers-only or unparseable-payload files.","triggerScenarios":"A video stream with zero decodable frames (container finalized after an interrupted write); a stream whose packets all fail to decode; files crafted with a video track header but no payloads.","commonSituations":"Interrupted uploads leaving truncated files; camera/screen-recorder stub files; corrupt transfers that preserve headers.","solutions":["Re-export or re-record the file (ffmpeg -i in.mp4 -c:v libx264 ref.mp4 rewrites a clean container and will fail loudly on truly dead sources).","Validate decodability before upload: ffmpeg -v error -i ref.mp4 -f null -.","Reject zero-frame files at the API boundary."],"exampleFix":"# before: headers-only upload -> ValueError('decoded to no frames')\nupload_reference(blob=truncated_bytes)\n\n# after: local sanity check before upload\nimport subprocess\nok = subprocess.run([\"ffmpeg\", \"-v\", \"error\", \"-i\", \"ref.mp4\", \"-f\", \"null\", \"-\"]).returncode == 0","handlingStrategy":"validation","validationCode":"import av, io\n\ndef yields_frames(blob: bytes) -> bool:\n    with av.open(io.BytesIO(blob)) as c:\n        if not c.streams.video:\n            return False\n        return next(iter(c.decode(video=0)), None) is not None","typeGuard":null,"tryCatchPattern":"try:\n    frames, wf, sr = decode_h3_reference_video(blob)\nexcept ValueError as e:\n    if str(e) == \"That reference video decoded to no frames.\":\n        return HTTPException(400, \"file has a video track but no frames; re-export it\")\n    raise","preventionTips":["Decode one frame as an upload sanity check when metadata looks valid.","Re-export suspect files with ffmpeg before blaming the pipeline.","Treat headers-only files as corrupt transfers."],"tags":["video","minimax-h3","upload","corrupt-file","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}