affaan-m/ECC · error · FileExistsError

output already exists; choose a new --out

Error message

output already exists; choose a new --out: {destination}

What it means

pipeline.py's main validates the final output via validate_output and, when not resuming with --takes, guards against overwriting existing artifacts: the .generation.json sidecar and the <stem>_takes directory. If either exists (or is a symlink), it raises FileExistsError before running any stages.

Solutions

  1. Choose a new --out path for the new run
  2. Delete or archive the reported .generation.json / <stem>_takes artifacts if the previous output is unwanted
  3. Pass --takes if you intend to resume/extend the existing output rather than create a fresh one
  4. Check both the output directory and its sidecar JSON for leftovers from failed runs before rerunning

Example fix

// before
python pipeline.py --genre noir --out cut.mov   # FileExistsError: cut.generation.json
// after
rm cut.generation.json && rm -rf cut_takes
python pipeline.py --genre noir --out cut.mov   # or pass --takes to resume
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
out = Path(out_path)
collisions = [out.with_suffix(".generation.json"), out.parent / f"{out.stem}_takes"]
existing = [d for d in collisions if d.exists() or d.is_symlink()]
if existing and not resume_takes:
    raise SystemExit(f"choose new --out or clean: {existing}")

Try / catch

try:
    pipeline.main()
except FileExistsError as e:
    print(e); pick_new_out_or_archive(existing)

Prevention

When it happens

Trigger: Re-running the pipeline with the same --out path after a prior complete or partial run left the generation JSON or takes directory in place, without passing --takes to resume.

Common situations: Iterating on the same output name after a previous run; leftover artifacts from a crashed run; symlinked output directories pointing at old results.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/25319bd131070a7a. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/pipeline.py:93

    if a.fps is not None and (not math.isfinite(a.fps) or a.fps <= 0):
        ap.error("--fps must be finite and positive")
    if a.takes and (a.prop or a.tier):
        ap.error("--takes cannot be combined with --prop or --tier")
    if a.takes and a.dry_run:
        print("[dry run] offline passthrough planned; no stages or files produced")
        return

    pack_dir = Path(a.root) / a.genre
    out = a.out or f"out/FINAL_{a.genre}.mp4"
    # Catch handoff collisions before optional distillation or prop spending.
    from forge import validate_output
    validate_output(Path(out))
    if not a.takes:
        for destination in (Path(out).with_suffix(".generation.json"),
                            Path(out).parent / f"{Path(out).stem}_takes"):
            if destination.exists() or destination.is_symlink():
                raise FileExistsError(f"output already exists; choose a new --out: {destination}")
    dry = ["--dry-run"] if a.dry_run else []

    # ---- 1. mint -------------------------------------------------------
    if a.remint or not (pack_dir / "grade.json").exists():
        if not a.refs:
            raise SystemExit(
                f"no pack at {pack_dir} and no --refs given; nothing to measure"
            )
        _run("mint", ["mint.py", "--genre", a.genre, "--root", a.root,
                      "--refs", *a.refs])
    else:
        print(f"[mint] reusing existing pack at {pack_dir} (--remint to re-measure)")

    # ---- 2. distill ----------------------------------------------------
    if not a.takes and not a.no_distill and (a.remint or not (pack_dir / "spec.json").exists()):
        _run("distill", ["distill.py", "--genre", a.genre, "--root", a.root, *dry])
    elif a.takes:
        print("[distill] skipped (offline passthrough)")

View on GitHub (pinned to 8321021c54)