{"record":{"id":"4603b46b287c9498","repo":"affaan-m/ECC","slug":"lut-not-found-lut","errorCode":null,"errorMessage":"LUT not found: {lut}","messagePattern":"LUT not found: (.+?)","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/taste/grade.py","lineNumber":663,"sourceCode":"    lut: str | Path,\n    strength: float = 1.0,\n    crf: int = 16,\n) -> Path:\n    \"\"\"Apply a pack's .cube to a clip with ffmpeg. This is where the look happens.\n\n    Measured on three generations against the flashethereal pack: prompting\n    for the grade moved midtone a* from +1.9 to +2.8 across two paid attempts\n    and never touched contrast (23.4 / 19.3 / 19.2 against a target of 34.7).\n    Running the same footage through this function put chroma within a mean\n    absolute error of 1.4 and contrast at 34.9 against 34.7 - in one pass, at\n    no marginal cost, and identically every time.\n\n    ``strength`` below 1.0 blends the graded result back toward the original,\n    for when the full pack look is too much for a particular shot.\n    \"\"\"\n    src, dst, lut = Path(src), Path(dst), Path(lut)\n    if not lut.exists():\n        raise FileNotFoundError(f\"LUT not found: {lut}\")\n    dst.parent.mkdir(parents=True, exist_ok=True)\n\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)","sourceCodeStart":645,"sourceCodeEnd":681,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/taste/grade.py#L645-L681","documentation":"`grade_clip()` applies a 3-D LUT to a video via FFmpeg and raises a FileNotFoundError when the LUT file does not exist on disk. It converts the lut argument to a Path and checks `.exists()` before constructing the ffmpeg filter graph, since FFmpeg's lut3d filter would otherwise fail with a less obvious error. The error message includes the exact path checked.","triggerScenarios":"Calling `grade_clip(src, dst, lut, ...)` where `Path(lut).exists()` is False — the .cube file path is wrong, the pack's LUT was deleted/moved, or a relative path is resolved from the wrong working directory.","commonSituations":"Referencing a style pack's LUT before running mint.py to generate it; typos in LUT filenames; scripts run from a different CWD so relative LUT paths break; renamed pack directories.","solutions":["Verify the LUT path exists before grading: `Path(lut).is_file()` and print/resolve it.","Regenerate the style pack (run mint.py) if the LUT is expected but missing.","Use absolute paths for LUTs, or anchor relative paths to the project root.","List the pack directory (`ls <pack>/luts/`) to find the actual LUT filename."],"exampleFix":"// before\ngrade_clip('in.mp4', 'out.mp4', lut='packs/mytaste/lut.cube')  # wrong dir\n// after\nlut = Path('packs/mytaste/lut.cube').resolve()\nif not lut.is_file():\n    raise FileNotFoundError(lut)\ngrade_clip('in.mp4', 'out.mp4', lut=lut)","handlingStrategy":"validation","validationCode":"from pathlib import Path\nlut = Path(lut)\nif not lut.is_file():\n    raise FileNotFoundError(f\"LUT missing: {lut}\")","typeGuard":"def lut_exists(lut: str | Path) -> bool:\n    return Path(lut).is_file() and Path(lut).suffix.lower() == '.cube'","tryCatchPattern":"try:\n    grade_clip(src, dst, lut=lut)\nexcept FileNotFoundError as e:\n    if str(e).startswith('LUT not found'):\n        mint_pack()   # regenerate\n        grade_clip(src, dst, lut=lut)\n    else:\n        raise","preventionTips":["Resolve LUT paths to absolute before grading","Regenerate style packs (mint.py) as part of setup, not per-shot","Check .cube existence in CI before batch renders","Avoid spaces/special chars in LUT paths to keep filter quoting safe"],"tags":["file-not-found","lut","ffmpeg","color-grading"],"backgroundTag":"file-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"}