nexu-io/open-design · warning · SystemExit

Output directory already exists: {output_dir}. Use --force t

Error message

Output directory already exists: {output_dir}. Use --force to overwrite.

What it means

Thrown by copy_template() when the output directory already exists and --force was not passed. Without --force the tool will neither overwrite nor merge, so it stops and asks for explicit consent.

Source

Thrown at skills/chat-motion-overlay/scripts/prepare_chat_overlay_bundle.py:72

        template_dir(),
    }
    if output_dir in dangerous_targets:
        raise SystemExit(
            f"Refusing to use dangerous output directory: {output_dir}. "
            "Choose a dedicated generated-bundle directory instead."
        )
    if output_dir.exists() and force and not bundle_marker_path(output_dir).exists():
        raise SystemExit(
            f"Refusing to overwrite unmanaged output directory: {output_dir}. "
            f"Only directories containing {BUNDLE_MARKER} can be replaced with --force."
        )


def copy_template(output_dir: Path, force: bool) -> None:
    validate_output_dir(output_dir, force)
    if output_dir.exists():
        if not force:
            raise SystemExit(f"Output directory already exists: {output_dir}. Use --force to overwrite.")
        shutil.rmtree(output_dir)
    shutil.copytree(template_dir(), output_dir)
    bundle_marker_path(output_dir).write_text("generated by chat-motion-overlay\n", encoding="utf-8")


def write_chat_spec_ts(spec: dict, output_dir: Path) -> None:
    target = output_dir / "src" / "chatSpec.ts"
    content = "export const chatSpec = " + json.dumps(spec, ensure_ascii=False, indent=2) + " as const;\n"
    target.write_text(content, encoding="utf-8")


def remove_local_upload_paths(spec: dict) -> None:
    for participant in spec["participants"]:
        participant.pop("uploadPath", None)


def copy_avatar_assets(spec: dict, output_dir: Path) -> dict:
    upload_sources: list[tuple[dict, Path]] = []

View on GitHub (pinned to 5be4028344)

Solutions

  1. Pass --force to overwrite a previously generated bundle (only works if the dir carries the BUNDLE_MARKER).
  2. Point --output-dir at a new unique directory for this run.
  3. Delete the existing directory first if you want a clean generation without --force.

Example fix

# before
python prepare_chat_overlay_bundle.py --output-dir ./bundle  # already exists
# after
python prepare_chat_overlay_bundle.py --output-dir ./bundle --force
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
def assert_output_ok(output_dir: Path, force: bool) -> None:
    if output_dir.exists() and not force:
        raise SystemExit(f"{output_dir} exists; pass --force or choose a new dir")

Prevention

When it happens

Trigger: Run prepare_chat_overlay_bundle.py --output-dir <existing dir> without the --force flag.

Common situations: Re-running the script after a previous successful bundle into the same folder; CI caching a bundle dir between runs; forgetting --force in a fresh-look wrapper script.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/bfd311cc3ff560dc. Report an issue: GitHub.