headroomlabs-ai/headroom · error · SystemExit

output directory must be empty to avoid stale artifacts: {pa

Error message

output directory must be empty to avoid stale artifacts: {path}

What it means

ensure_empty_dir() in the Python release smoke script creates the output directory and refuses to proceed if it already contains anything. The check exists so each smoke run verifies artifacts it built itself, never stale wheels or sdists from an earlier run.

Source

Thrown at scripts/build_python_release_smoke.py:59

    if re.fullmatch(r"[A-Za-z0-9_./:=\\-]+", text):
        return text
    return f'"{text.replace(chr(34), chr(34) * 2)}"'


def run(
    args: list[str | os.PathLike[str]],
    *,
    env: dict[str, str] | None = None,
    cwd: Path = ROOT,
) -> None:
    print("\n> " + " ".join(quote_arg(arg) for arg in args), flush=True)
    subprocess.run([str(arg) for arg in args], cwd=cwd, env=env, check=True)


def ensure_empty_dir(path: Path) -> None:
    path.mkdir(parents=True, exist_ok=True)
    if any(path.iterdir()):
        raise SystemExit(f"output directory must be empty to avoid stale artifacts: {path}")


def build_artifacts(out_dir: Path, python_exe: str, profile: str, release: bool) -> None:
    env = os.environ.copy()
    env.setdefault("PYO3_USE_ABI3_FORWARD_COMPATIBILITY", "1")

    run([python_exe, "-m", "maturin", "--version"], env=env)

    build_args = [
        python_exe,
        "-m",
        "maturin",
        "build",
        "--out",
        out_dir,
        "--interpreter",
        python_exe,
    ]

View on GitHub (pinned to 322425c43b)

Solutions

  1. Point `--out` at a fresh directory (the default in release_smoke_all.py already appends a version + timestamp stamp).
  2. Or empty the directory first: `rm -rf <out_dir>/*` and rerun.
  3. If this repeats in CI, make the job clean or unique-name its output dir instead of disabling the check.

Example fix

# before
python scripts/build_python_release_smoke.py --out ./smoke-out
# fails when ./smoke-out already has files

# after
rm -rf ./smoke-out && python scripts/build_python_release_smoke.py --out ./smoke-out
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def fresh_out_dir(path: Path) -> Path:
    import time
    candidate = path if not any(path.glob("*")) else path.with_name(f"{path.name}-{time.strftime('%Y%m%d-%H%M%S')}")
    candidate.mkdir(parents=True, exist_ok=True)
    assert not any(candidate.iterdir()), candidate
    return candidate

Prevention

When it happens

Trigger: Passing `--out <dir>` pointing at a directory that already holds files; rerunning the smoke into a hand-created output dir; a previous crashed run leaving partial maturin output behind.

Common situations: Iterating on release tooling and reusing a fixed output path like `./dist`; CI retrying a job into a cached workspace directory; a timeout killing maturin mid-build so the dir is dirty on the next attempt.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/4b2071960a248bac. Report an issue: GitHub.