affaan-m/ECC · error · ValueError
asset must be a local regular file
Error message
asset must be a local regular file: {asset} What it means
After type-checking, allocate_placements expands/resolves the asset path and requires it to exist as a regular file; it raises ValueError('asset must be a local regular file: {asset}') when Path.is_file() is false — the path doesn't exist, is a directory, or is a symlink/special file pointing to nothing regular.
Solutions
- Check `os.path.isfile(asset)` before calling and print the resolved path to see where it points
- Use absolute paths (or expanduser/resolve yourself) so cwd changes don't break the run
- Verify the upstream step that produces the asset succeeded and the file still exists at render time
- If it's a directory or URL, point to a regular file instead (e.g. the video file inside the directory)
Example fix
# before
resolve.apply_placements(..., [{'id': 'x', 'asset': 'overlay.webm'}]) # missing file
# after
from pathlib import Path
p = Path('overlay.webm').expanduser().resolve()
if not p.is_file():
raise FileNotFoundError(f'overlay asset missing: {p}')
resolve.apply_placements(..., [{'id': 'x', 'asset': p}]) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def ensure_assets_exist(events):
for ev in events:
a = Path(str(ev.get('asset', ''))).expanduser().resolve()
if not a.is_file():
raise FileNotFoundError(f'placement {ev.get("id")!r} asset missing: {a}')
ensure_assets_exist(placements) Try / catch
try:
resolve.apply_placements(plan, placements)
except ValueError as e:
if e.args and e.args[0].startswith('asset must be a local regular file:'):
missing = e.args[0].rsplit(': ', 1)[1]
raise AssetError(f'missing overlay asset: {missing}') from e
raise Prevention
- Use absolute, resolved paths in configs so cwd doesn't matter
- Verify all assets exist at pipeline start, fail fast before long renders
- Ensure asset-producing steps complete before compositing
When it happens
Trigger: Passing a path that was never created, a deleted temp file, a directory path, a broken symlink, a relative path wrong for the current working directory, or a device/pipe special file.
Common situations: Renders run from a different cwd than where relative asset paths were authored; assets generated by an earlier pipeline step that failed silently; assets cleaned up before compositing; using '~/asset.webm' where ~ isn't expanded (though expanduser handles it, the file must exist after resolution).
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
- FileNotFoundError(source)
- Agents directory not found
- asset must be a local regular file
- asset must contain a video stream
- cannot open
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/dec171d4e4104d7a.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/resolve.py:118
raise ValueError("placement id must be unique and nonempty")
seen.add(identifier)
start = _integer(event.get("record_frame"), "record_frame")
frames = _integer(event.get("frames"), "frames", 1)
opacity = event.get("opacity")
if (
isinstance(opacity, bool)
or not isinstance(opacity, (int, float))
or not math.isfinite(opacity)
or not 0 <= opacity <= 100
):
raise ValueError("explicit opacity must be finite within 0..100")
composite = _integer(event.get("composite"), "composite")
raw_asset = event.get("asset")
if not isinstance(raw_asset, (str, Path)) or not str(raw_asset):
raise ValueError("asset must be a local regular file")
asset = Path(raw_asset).expanduser().resolve()
if not asset.is_file():
raise ValueError(f"asset must be a local regular file: {asset}")
alpha = event.get("requires_alpha", False)
if not isinstance(alpha, bool):
raise ValueError("requires_alpha must be boolean")
key = str(asset)
if key not in metadata:
metadata[key] = probe(asset)
info = metadata[key]
if _fps(info.get("fps")) != rate:
raise ValueError(f"asset fps differs from timeline: {asset}")
if _integer(info.get("frames"), "asset frames", 1) < frames:
raise ValueError(f"asset contains too few frames: {asset}")
if alpha and info.get("has_alpha") is not True:
raise ValueError(f"asset requires verified alpha: {asset}")
checked.append(
{
"id": identifier,
"asset": key,
"record_frame": start,View on GitHub (pinned to 8321021c54)