{"record":{"id":"dec171d4e4104d7a","repo":"affaan-m/ECC","slug":"asset-must-be-a-local-regular-file-asset","errorCode":null,"errorMessage":"asset must be a local regular file: {asset}","messagePattern":"asset must be a local regular file: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/resolve.py","lineNumber":118,"sourceCode":"            raise ValueError(\"placement id must be unique and nonempty\")\n        seen.add(identifier)\n        start = _integer(event.get(\"record_frame\"), \"record_frame\")\n        frames = _integer(event.get(\"frames\"), \"frames\", 1)\n        opacity = event.get(\"opacity\")\n        if (\n            isinstance(opacity, bool)\n            or not isinstance(opacity, (int, float))\n            or not math.isfinite(opacity)\n            or not 0 <= opacity <= 100\n        ):\n            raise ValueError(\"explicit opacity must be finite within 0..100\")\n        composite = _integer(event.get(\"composite\"), \"composite\")\n        raw_asset = event.get(\"asset\")\n        if not isinstance(raw_asset, (str, Path)) or not str(raw_asset):\n            raise ValueError(\"asset must be a local regular file\")\n        asset = Path(raw_asset).expanduser().resolve()\n        if not asset.is_file():\n            raise ValueError(f\"asset must be a local regular file: {asset}\")\n        alpha = event.get(\"requires_alpha\", False)\n        if not isinstance(alpha, bool):\n            raise ValueError(\"requires_alpha must be boolean\")\n        key = str(asset)\n        if key not in metadata:\n            metadata[key] = probe(asset)\n        info = metadata[key]\n        if _fps(info.get(\"fps\")) != rate:\n            raise ValueError(f\"asset fps differs from timeline: {asset}\")\n        if _integer(info.get(\"frames\"), \"asset frames\", 1) < frames:\n            raise ValueError(f\"asset contains too few frames: {asset}\")\n        if alpha and info.get(\"has_alpha\") is not True:\n            raise ValueError(f\"asset requires verified alpha: {asset}\")\n        checked.append(\n            {\n                \"id\": identifier,\n                \"asset\": key,\n                \"record_frame\": start,","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/resolve.py#L100-L136","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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)"],"exampleFix":"# before\nresolve.apply_placements(..., [{'id': 'x', 'asset': 'overlay.webm'}])  # missing file\n# after\nfrom pathlib import Path\np = Path('overlay.webm').expanduser().resolve()\nif not p.is_file():\n    raise FileNotFoundError(f'overlay asset missing: {p}')\nresolve.apply_placements(..., [{'id': 'x', 'asset': p}])","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef ensure_assets_exist(events):\n    for ev in events:\n        a = Path(str(ev.get('asset', ''))).expanduser().resolve()\n        if not a.is_file():\n            raise FileNotFoundError(f'placement {ev.get(\"id\")!r} asset missing: {a}')\n\nensure_assets_exist(placements)","typeGuard":null,"tryCatchPattern":"try:\n    resolve.apply_placements(plan, placements)\nexcept ValueError as e:\n    if e.args and e.args[0].startswith('asset must be a local regular file:'):\n        missing = e.args[0].rsplit(': ', 1)[1]\n        raise AssetError(f'missing overlay asset: {missing}') from e\n    raise","preventionTips":["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"],"tags":["file-not-found","asset","paths"],"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"}