{"record":{"id":"69c9688769394cc7","repo":"affaan-m/ECC","slug":"output-already-exists-choose-a-new-out-path","errorCode":null,"errorMessage":"output already exists; choose a new --out: {path}","messagePattern":"output already exists; choose a new --out: (.+?)","errorType":"exception","errorClass":"FileExistsError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/forge.py","lineNumber":46,"sourceCode":"import numpy as np\n\nfrom taste import assemble as asm\nfrom taste import cadence as cad_mod\nfrom taste import frames as frame_mod\nfrom taste import grade as grade_mod\nfrom taste import pack as pack_mod\nfrom taste import plates as plate_mod\nfrom taste import timeline as tl_mod\n\n\ndef validate_output(out_path: Path) -> None:\n    \"\"\"Refuse to replace either a viewing copy or any part of its handoff.\"\"\"\n    outputs = [out_path, *(out_path.with_suffix(s) for s in (\".fcpxml\", \".edl\", \".json\"))]\n    if len(set(outputs)) != len(outputs):\n        raise ValueError(\"output must have a video suffix distinct from timeline/manifest files\")\n    for path in outputs:\n        if path.exists() or path.is_symlink():\n            raise FileExistsError(f\"output already exists; choose a new --out: {path}\")\n\n\ndef forge(\n    genre: str,\n    takes: list[str],\n    out: str,\n    root: str = \"stylepacks\",\n    base_video: str | None = None,\n    base_ratio: float = 0.35,\n    overlays: list[str] | None = None,\n    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\",","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/forge.py#L28-L64","documentation":"validate_output() refuses to overwrite existing files: it checks the output video path and its derived .fcpxml, .edl, .json siblings and raises FileExistsError if any exists (including dangling symlinks). This protects prior edits — each run's timelines reference shot files, so an accidental overwrite would destroy a previous edit.","triggerScenarios":"Running forge twice with the same --out; an output, timeline, or manifest from a previous run still present at the target location; a leftover symlink at any of the four paths.","commonSituations":"Re-running a failed or successful job without changing --out; scheduled scripts reusing a fixed output name; resuming work in a directory that already contains edit.mp4/edit.fcpxml.","solutions":["Choose a new --out path for the run.","Deliberately archive or delete the old output set (the video plus its .fcpxml/.edl/.json) before rerunning.","In automation, generate a unique name, e.g. out = f'edit_{datetime.now():%Y%m%d%H%M%S}.mp4'."],"exampleFix":"# before\nforge('noir', takes, out='edit.mp4')  # second run: exists\n\n# after\nfrom datetime import datetime\nforge('noir', takes, out=f\"edit_{datetime.now():%Y%m%d%H%M%S}.mp4\")","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef output_is_free(out):\n    p = Path(out)\n    return not any(x.exists() or x.is_symlink()\n                   for x in [p, *(p.with_suffix(s) for s in ('.fcpxml', '.edl', '.json'))])","typeGuard":null,"tryCatchPattern":"try:\n    forge(genre, takes, out=out)\nexcept FileExistsError as e:\n    print(f'pick a new --out: {e}')","preventionTips":["Generate unique output names (timestamp/uuid suffix) in automated runs.","Check all four paths (video, .fcpxml, .edl, .json) for existence before rerunning.","Treat the error as intentional protection — archive prior edits instead of deleting them reflexively."],"tags":["cli","filesystem","validation","idempotency"],"backgroundTag":"file-already-exists","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"}