affaan-m/ECC · error · FileNotFoundError
LUT not found
Error message
LUT not found: {lut} What it means
`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.
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.
Example fix
// before
grade_clip('in.mp4', 'out.mp4', lut='packs/mytaste/lut.cube') # wrong dir
// after
lut = Path('packs/mytaste/lut.cube').resolve()
if not lut.is_file():
raise FileNotFoundError(lut)
grade_clip('in.mp4', 'out.mp4', lut=lut) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
lut = Path(lut)
if not lut.is_file():
raise FileNotFoundError(f"LUT missing: {lut}") Type guard
def lut_exists(lut: str | Path) -> bool:
return Path(lut).is_file() and Path(lut).suffix.lower() == '.cube' Try / catch
try:
grade_clip(src, dst, lut=lut)
except FileNotFoundError as e:
if str(e).startswith('LUT not found'):
mint_pack() # regenerate
grade_clip(src, dst, lut=lut)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- ffmpeg grade failed
- FileNotFoundError(source)
- Agents directory not found
- analyze() needs at least one frame
- asset must be a local regular file
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/4603b46b287c9498.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/taste/grade.py:663
lut: str | Path,
strength: float = 1.0,
crf: int = 16,
) -> Path:
"""Apply a pack's .cube to a clip with ffmpeg. This is where the look happens.
Measured on three generations against the flashethereal pack: prompting
for the grade moved midtone a* from +1.9 to +2.8 across two paid attempts
and never touched contrast (23.4 / 19.3 / 19.2 against a target of 34.7).
Running the same footage through this function put chroma within a mean
absolute error of 1.4 and contrast at 34.9 against 34.7 - in one pass, at
no marginal cost, and identically every time.
``strength`` below 1.0 blends the graded result back toward the original,
for when the full pack look is too much for a particular shot.
"""
src, dst, lut = Path(src), Path(dst), Path(lut)
if not lut.exists():
raise FileNotFoundError(f"LUT not found: {lut}")
dst.parent.mkdir(parents=True, exist_ok=True)
s = max(0.0, min(1.0, float(strength)))
if s >= 0.999:
vf = f"lut3d=file='{lut.as_posix()}'"
else:
# Blend graded over original so partial looks stay available.
vf = (
f"split=2[a][b];[b]lut3d=file='{lut.as_posix()}'[g];"
f"[a][g]blend=all_mode=normal:all_opacity={s:.3f}"
)
cmd = [
"ffmpeg", "-nostdin", "-loglevel", "error", "-y", "-i", str(src),
"-vf", vf, "-c:v", "libx264", "-crf", str(crf), "-pix_fmt", "yuv420p",
"-c:a", "copy", str(dst),
]
proc = subprocess.run(cmd, capture_output=True, text=True)View on GitHub (pinned to 8321021c54)