GyulyVGC/sniffnet · error · SystemExit
Refusing to overwrite an existing release in
Error message
Refusing to overwrite an existing release in {output}; use --output with a fresh directory What it means
prepare() refuses to build a Debian source release into an --output directory that already exists and contains files. This guard prevents silently mixing a new release with stale artifacts from a previous run (or clobbering files the user wants kept). It aborts before any staging work so no partial output is written.
Solutions
- Delete or empty the output directory (rm -rf target/debian-source) and re-run
- Pass --output with a fresh, non-existent or empty directory path
- If the previous run's artifacts are wanted, move them aside before re-running
Example fix
// before python3 prepare.py # after rm -rf target/debian-source && python3 prepare.py # or python3 prepare.py --output /tmp/deb-out-v1.3.1
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
output = Path(args.output).resolve()
if output.exists() and any(output.iterdir()):
raise SystemExit(f"Output directory {output} is not empty; choose a fresh --output") Type guard
def is_fresh_output_dir(p: Path) -> bool:
return not p.exists() or not any(p.iterdir()) Try / catch
try:
prepare(output)
except SystemExit as e:
print(f"Packaging aborted: {e}", file=sys.stderr)
sys.exit(2) Prevention
- Always invoke with a fresh --output path per release version
- Add a pre-run cleanup step (rm -rf target/debian-source) in CI scripts
- Never reuse the default output directory across versions
- Check the directory contents before running if resuming an interrupted build
When it happens
Trigger: Running prepare.py with --output pointing at a directory that exists and is non-empty; most commonly re-running the script with the same (default target/debian-source) output directory after a previous successful or partial run.
Common situations: Re-running the packager after a failed build left artifacts behind; running twice for the same version; pointing --output at a shared or pre-created release directory; forgetting that the default output dir persists between runs.
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.
AI-assisted analysis of GyulyVGC/sniffnet@592a62a5ad (2026-09-18).
Data as JSON: /api/errors/39221c168c4c85d8.
Report an issue: GitHub.
Appendix: source
Thrown at resources/packaging/linux/deb-source/prepare.py:28
import shutil
import subprocess
import sys
import tarfile
import tempfile
import tomllib
ROOT = Path(__file__).resolve().parents[4]
DEBIAN = Path(__file__).resolve().parent / "debian"
def run(*args, cwd=ROOT, **kwargs):
return subprocess.run(args, cwd=cwd, check=True, **kwargs)
def prepare(output):
if output.exists() and any(output.iterdir()):
raise SystemExit(f"Refusing to overwrite an existing release in {output}; use --output with a fresh directory")
# Stage outside the checkout so Cargo cannot inherit a newer parent workspace.
with tempfile.TemporaryDirectory(prefix="sniffnet-debian-") as staging:
source = prepare_staged(Path(staging))
output.mkdir(parents=True, exist_ok=True)
for path in Path(staging).iterdir():
shutil.move(str(path), output / path.name)
print(f"Release files: {output}", flush=True)
return output / source.name
def prepare_staged(output):
changelog = (DEBIAN / "changelog").read_text()
match = re.match(r"sniffnet \(([^)]+)\) ([\w-]+);", changelog)
if not match:
raise SystemExit("Cannot parse debian/changelog")
version = match[1].rsplit("-", 1)[0]
tag = f"refs/tags/v{version}"
commit = run("git", "rev-parse", "--verify", f"{tag}^{{commit}}",View on GitHub (pinned to 592a62a5ad)