GyulyVGC/sniffnet · error · SystemExit

debian/changelog must match the tagged Cargo.toml version

Error message

debian/changelog must match the tagged Cargo.toml version

What it means

prepare_staged() cross-checks the version parsed from debian/changelog against the 'package.version' field of Cargo.toml at the commit the corresponding git tag (v<version>) points to. If the tagged manifest's version differs from the changelog version, the script aborts, because the Debian source package would claim a version that does not match the upstream code it packages.

Solutions

  1. Make Cargo.toml's package.version in the commit tagged v<version> equal the changelog version, then re-tag (git tag -f vX.Y.Z && git push -f origin vX.Y.Z)
  2. Update debian/changelog to the version that the existing tag actually carries
  3. Verify the tag points at the intended commit: git rev-parse --verify refs/tags/vX.Y.Z^{commit}

Example fix

// before (Cargo.toml at tag v1.3.1)
version = "1.3.0"
# after
version = "1.3.1"
# then: git add Cargo.toml && git commit && git tag -f v1.3.1
Defensive patterns

Strategy: validation

Validate before calling

version = re.search(r"sniffnet \(([^)]+)\)", changelog_text).group(1).rsplit("-", 1)[0]
commit = subprocess.run(["git", "rev-parse", "--verify", f"refs/tags/v{version}^{{commit}}"],
                        capture_output=True, text=True, check=True).stdout.strip()
cargo_version = tomllib.loads(subprocess.run(["git", "show", f"{commit}:Cargo.toml"],
                        capture_output=True, text=True, check=True).stdout)["package"]["version"]
if cargo_version != version:
    raise SystemExit(f"Tag v{version} has Cargo.toml version {cargo_version}; align before packaging")

Type guard

def versions_are_consistent(changelog_version: str, cargo_version: str) -> bool:
    return changelog_version == cargo_version

Try / catch

try:
    prepare(output)
except SystemExit as e:
    if "must match the tagged Cargo.toml version" in str(e):
        print("Bump Cargo.toml (or the changelog) and re-tag: git tag -f vX.Y.Z", file=sys.stderr)
    raise

Prevention

When it happens

Trigger: Running prepare.py when debian/changelog says e.g. 1.3.1 but refs/tags/v1.3.1's Cargo.toml has version '1.3.0' — i.e. the changelog was bumped without tagging a matching release, the tag points at the wrong commit, or Cargo.toml version was edited after tagging.

Common situations: Bumping debian/changelog for a release before creating the git tag; tagging a release but forgetting to bump Cargo.toml in the tagged commit; a Debian revision suffix (-1) being handled but the base version diverging from the tag; moving a tag to a different commit after the changelog was written.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of GyulyVGC/sniffnet@592a62a5ad (2026-09-18). Data as JSON: /api/errors/08875070460ee882. Report an issue: GitHub.

Appendix: source

Thrown at resources/packaging/linux/deb-source/prepare.py:51

        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}}",
                 capture_output=True, text=True).stdout.strip()
    manifest = tomllib.loads(run("git", "show", f"{commit}:Cargo.toml",
                                capture_output=True, text=True).stdout)
    if manifest["package"]["version"] != version:
        raise SystemExit("debian/changelog must match the tagged Cargo.toml version")
    source = output / f"sniffnet-{version}"
    archive = output / f"sniffnet_{version}.orig.tar.gz"
    if source.exists() or archive.exists():
        raise SystemExit(f"Refusing to overwrite an existing release in {output}; use --output with a fresh directory")
    epoch = int(run("git", "show", "-s", "--format=%ct", commit,
                    capture_output=True, text=True).stdout)
    output.mkdir(parents=True, exist_ok=True)
    source.mkdir()

    # Extract only release-tag inputs. A branch with the same name cannot win
    # ref resolution, and local application edits cannot enter the package.
    snapshot = run("git", "archive", "--format=tar", commit,
                   capture_output=True).stdout
    run("tar", "-xf", "-", cwd=source, input=snapshot)
    # Overlay current Debian packaging after creating the upstream archive.
    if (source / "debian").exists():
        shutil.rmtree(source / "debian")
    print(f"Upstream tag: {tag}\nUpstream commit: {commit}", flush=True)

View on GitHub (pinned to 592a62a5ad)