{"record":{"id":"8d2e75e3819dc2e2","repo":"affaan-m/ECC","slug":"all-overlays-must-be-readable-local-files","errorCode":null,"errorMessage":"all overlays must be readable local files","messagePattern":"all overlays must be readable local files","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/forge.py","lineNumber":75,"sourceCode":"    overlay_every: int = 4,\n    overlay_opacity: float = 0.3,\n    duration: float | None = None,\n    strength: float = 1.0,\n    grade_base: bool = True,\n    width: int | None = None,\n    height: int | None = None,\n    work: str = \"out/forge_work\",\n    plan: list[dict] | None = None,\n    fps: float | None = None,\n) -> Path:\n    out_path = Path(out)\n    validate_output(out_path)\n    if not takes or any(not Path(t).is_file() for t in takes):\n        raise ValueError(\"all takes must be readable local files\")\n    if base_video and not Path(base_video).is_file():\n        raise ValueError(\"base video must be a readable local file\")\n    if any(not Path(o).is_file() for o in (overlays or [])):\n        raise ValueError(\"all overlays must be readable local files\")\n    if fps is not None and (not math.isfinite(fps) or fps <= 0):\n        raise ValueError(\"fps must be finite and positive\")\n    sp = pack_mod.load(genre, root=root)\n    tgt = grade_mod.load_stats(sp.grade_path)\n    cad = cad_mod.load(sp.cadence_path)\n\n    # Geometry comes from the first take unless overridden; everything else is\n    # normalized to it so concat does not silently fail on a size mismatch.\n    info0 = frame_mod.probe(takes[0])\n    W = width or info0.width\n    H = height or info0.height\n    FPS = fps if fps is not None else info0.fps\n    if not math.isfinite(FPS) or FPS <= 0:\n        raise ValueError(\"source fps must be finite and positive; provide --fps\")\n    if W <= 0 or H <= 0:\n        raise ValueError(\"output width and height must be positive\")\n    # Prior timelines reference these shot files. Each run owns a fresh child,\n    # including failed runs, so retries cannot erase an existing edit.","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/forge.py#L57-L93","documentation":"forge() validates every entry of the optional overlays list: each overlay must be an existing regular local file. If any overlay path is missing or is not a file, it raises ValueError before processing begins.","triggerScenarios":"Passing overlays=['img/watermark.png'] where the PNG was deleted or renamed; passing a directory; passing remote URLs or glob-unexpanded patterns ('*.png') as overlay entries.","commonSituations":"Assets folder reorganized so overlay paths changed; forgetting that glob patterns are not expanded when calling forge() programmatically; overlays generated by a previous step that failed silently.","solutions":["Filter to existing files first: [o for o in overlays if Path(o).is_file()].","Expand globs explicitly before the call: sorted(glob('overlays/*.png')).","Regenerate the overlay assets if an upstream step failed to create them.","Use absolute paths for overlay assets."],"exampleFix":"# before\nforge('noir', takes, overlays=['overlays/*.png'], out='edit.mp4')  # glob not expanded\n\n# after\nimport glob\noverlays = [o for o in sorted(glob.glob('overlays/*.png')) if Path(o).is_file()]\nforge('noir', takes, overlays=overlays, out='edit.mp4')","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef overlays_ok(overlays):\n    return all(Path(o).is_file() for o in (overlays or []))","typeGuard":null,"tryCatchPattern":"try:\n    forge(genre, takes, overlays=overlays, out=out)\nexcept ValueError as e:\n    if 'overlays' in str(e):\n        print('missing overlays:', [o for o in overlays if not Path(o).is_file()])\n    raise","preventionTips":["Expand glob patterns yourself with glob.glob before passing overlays.","Filter to existing files and log dropped entries.","Verify upstream asset-generation steps succeeded before forging."],"tags":["cli","validation","filesystem","input"],"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"}