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

  1. Verify the LUT path exists before grading: `Path(lut).is_file()` and print/resolve it.
  2. Regenerate the style pack (run mint.py) if the LUT is expected but missing.
  3. Use absolute paths for LUTs, or anchor relative paths to the project root.
  4. 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

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


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)