{"record":{"id":"79340a4ca20c4d21","repo":"affaan-m/ECC","slug":"ffmpeg-grade-failed-proc-stderr-400","errorCode":null,"errorMessage":"ffmpeg grade failed: {proc.stderr[-400:]}","messagePattern":"ffmpeg grade failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/taste/grade.py","lineNumber":683,"sourceCode":"\n    s = max(0.0, min(1.0, float(strength)))\n    if s >= 0.999:\n        vf = f\"lut3d=file='{lut.as_posix()}'\"\n    else:\n        # Blend graded over original so partial looks stay available.\n        vf = (\n            f\"split=2[a][b];[b]lut3d=file='{lut.as_posix()}'[g];\"\n            f\"[a][g]blend=all_mode=normal:all_opacity={s:.3f}\"\n        )\n\n    cmd = [\n        \"ffmpeg\", \"-nostdin\", \"-loglevel\", \"error\", \"-y\", \"-i\", str(src),\n        \"-vf\", vf, \"-c:v\", \"libx264\", \"-crf\", str(crf), \"-pix_fmt\", \"yuv420p\",\n        \"-c:a\", \"copy\", str(dst),\n    ]\n    proc = subprocess.run(cmd, capture_output=True, text=True)\n    if proc.returncode != 0:\n        raise RuntimeError(f\"ffmpeg grade failed: {proc.stderr[-400:]}\")\n    return dst\n\n\ndef grade_clip_adaptive(\n    src: str | Path,\n    dst: str | Path,\n    target: GradeStats,\n    strength: float = 1.0,\n    lut_size: int = 33,\n    n_frames: int = 32,\n    keep_lut: str | Path | None = None,\n) -> Path:\n    \"\"\"Measure the clip, bake a LUT *for that clip*, then apply it.\n\n    Prefer this over :func:`grade_clip` for anything generated.\n\n    ``look.cube`` is baked against a canonical neutral stand-in, because when\n    a pack is minted there is no way to know what footage it will meet. That","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/taste/grade.py#L665-L701","documentation":"`grade_clip()` shells out to FFmpeg with `-loglevel error` and raises a RuntimeError when the ffmpeg process exits non-zero, including the last 400 bytes of FFmpeg's stderr. This surfaces real encoding/filter failures (bad input file, unsupported filter syntax, codec issues, disk full). The truncated stderr is the primary diagnostic for why the grade failed.","triggerScenarios":"Calling `grade_clip()` where the subprocess returns returncode != 0 — e.g. the source video is corrupt/unreadable, the lut3d filter path quoting fails, the output path is unwritable, or ffmpeg is missing/misbehaving.","commonSituations":"Spaces or special characters in LUT paths breaking the `file='...'` filter quoting; source video with unsupported pixel format for libx264; destination directory lacking write permission; old FFmpeg without lut3d support.","solutions":["Read the embedded stderr (last 400 chars in the exception message) — it names the exact FFmpeg failure.","Check the source video with `ffprobe`; re-encode or remux if it is corrupt.","Upgrade FFmpeg (`ffmpeg -version`) to one supporting `lut3d`; quote/escape the LUT path if it contains spaces.","Test writing to the destination directory (`touch dst_dir/.probe`) to rule out permission problems."],"exampleFix":"// before\nvf = f\"lut3d=file='{lut.as_posix()}\"   # broken quoting -> ffmpeg fails\n// after\nvf = f\"lut3d=file='{lut.as_posix()}'\"  # properly closed quote\nsubprocess.run(cmd, capture_output=True, text=True, check=False)","handlingStrategy":"try-catch","validationCode":"import shutil\nassert shutil.which('ffmpeg'), 'ffmpeg not on PATH'\nassert Path(src).is_file(), f'missing source: {src}'","typeGuard":null,"tryCatchPattern":"try:\n    grade_clip(src, dst, lut)\nexcept RuntimeError as e:\n    if str(e).startswith('ffmpeg grade failed'):\n        logger.error('ffmpeg stderr: %s', e)\n        raise GradeError(dst, stderr=str(e)) from e\n    raise","preventionTips":["Log the full ffmpeg stderr, not just the message","Pin a modern FFmpeg version with lut3d and libx264 support","Quote/escape paths inside -vf filter strings","Free disk space and verify write permissions before encodes"],"tags":["ffmpeg","subprocess","video-encoding","color-grading"],"backgroundTag":"command-not-found","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}