unslothai/unsloth · error · RuntimeError
GIF export failed to decode the clip: {exc}
Error message
GIF export failed to decode the clip: {exc} What it means
The catch-all of the GIF decode loop: any non-RuntimeError exception while demuxing/decoding frames or downscaling/resampling to paletted images is wrapped as 'GIF export failed to decode the clip' with the original exception attached. Deliberate RuntimeErrors from inside the try (no video stream) pass through unchanged.
Source
Thrown at studio/backend/core/inference/video_gallery.py:251
step = -(-total // _GIF_MAX_FRAMES)
for i, frame in enumerate(src.decode(in_v)):
if i % step:
continue
if len(frames) >= _GIF_MAX_FRAMES:
# Frame count unknown up front (no stream metadata): stop at the cap.
break
image = frame.to_image()
if max(image.size) > _GIF_MAX_EDGE:
scale = _GIF_MAX_EDGE / max(image.size)
image = image.resize(
(max(1, round(image.width * scale)), max(1, round(image.height * scale))),
Image.Resampling.LANCZOS,
)
frames.append(image.convert("P", palette = Image.Palette.ADAPTIVE))
except RuntimeError:
raise
except Exception as exc: # noqa: BLE001 -- surface as "decoder unavailable"
raise RuntimeError(f"GIF export failed to decode the clip: {exc}") from exc
if not frames:
raise RuntimeError("GIF export decoded no frames.")
duration_ms = max(20, int(1000 * step / rate))
buf = io.BytesIO()
frames[0].save(
buf,
format = "GIF",
save_all = True,
append_images = frames[1:],
duration = duration_ms,
loop = 0,
)
return buf.getvalue()
def _sidecar_path(video_id: str) -> Path:
return gallery_dir() / f"{video_id}.json"
View on GitHub (pinned to 203007d190)
Solutions
- Inspect the chained {exc} to identify the failing frame/codec.
- Verify the clip decodes standalone: ffmpeg -v error -i clip.mp4 -f null - to surface corruption.
- Reinstall av (pip install --force-reinstall av) if a missing decoder is at fault.
- Regenerate the source clip if it is corrupt.
Example fix
# before: exporting a truncated clip -> RuntimeError('failed to decode')
# after: validate decodability first
import subprocess, sys
rc = subprocess.run(["ffmpeg", "-v", "error", "-i", str(p), "-f", "null", "-"]).returncode
if rc != 0:
raise HTTPException(400, "clip is not decodable; regenerate it") Defensive patterns
Strategy: try-catch
Validate before calling
import subprocess
def decodable(path) -> bool:
return subprocess.run(
["ffmpeg", "-v", "error", "-i", str(path), "-f", "null", "-"],
capture_output=True,
).returncode == 0 Try / catch
try:
gif = _transcode_gif(path)
except RuntimeError as e:
if "failed to decode" in str(e):
log.warning("clip corrupt: %s", e.__cause__)
raise HTTPException(400, "clip is corrupt; regenerate it") from e
raise Prevention
- Decode-validate generated clips as part of the generation job itself.
- Inspect __cause__ — it carries the real decode error.
- Keep ffmpeg installed in ops environments for quick ffprobe triage.
When it happens
Trigger: Corrupt or truncated clip raising av.FFVDecodeError / InvalidDataException mid-loop; a codec the installed PyAV build cannot decode; malformed frame dimensions breaking the PIL resize/resample step.
Common situations: Clips truncated by a crashed generation job or interrupted file transfer; exotic codecs in user uploads; PyAV builds missing decoders.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- GIF export failed: the clip has no video stream.
- WebM export failed: the clip has no video stream.
- GIF export needs the 'av' and 'Pillow' packages.
- GIF export decoded no frames.
- That reference video decoded to no frames.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/7de7163affbc5b3a.
Report an issue: GitHub.