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

  1. Inspect the chained {exc} to identify the failing frame/codec.
  2. Verify the clip decodes standalone: ffmpeg -v error -i clip.mp4 -f null - to surface corruption.
  3. Reinstall av (pip install --force-reinstall av) if a missing decoder is at fault.
  4. 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

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

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/7de7163affbc5b3a. Report an issue: GitHub.