stamparm/maltrail · error · SystemExit

[!] no version key found in

Error message

[!] no version key found in %s

What it means

check_version.py extracts the version from CITATION.cff with a regex over a 'version:' key. If the file exists but has no version key (or it's formatted unusually, e.g. unquoted or different indentation/spacing), the regex fails and the tool exits with this message rather than silently returning a wrong version. This guards the release pipeline from citing the wrong paper version.

Solutions

  1. Open CITATION.cff and add/restore a top-level version key: version: "3.2"
  2. Check the key uses 'version:' with regular spaces before the value and the value is quoted
  3. Run check_version.py again to confirm all version sources agree
  4. Validate the file with a CFF validator (cffconvert) to catch other schema issues

Example fix

// before (CITATION.cff missing key)
# CITATION.cff
authors:
  - ...
// after
authors:
  - ...
version: "3.2"
Defensive patterns

Strategy: validation

Validate before calling

import re, pathlib
text = pathlib.Path("CITATION.cff").read_text()
assert re.search(r'^version\s*:\s*["\'][^"\']+["\']', text, re.M), "CITATION.cff missing version key"

Prevention

When it happens

Trigger: Running check_version.py (via main) when sensor/../CITATION.cff lacks a line matching ^version: "..." — e.g. the key was renamed, removed, uses no quotes, or uses tabs instead of spaces after the colon.

Common situations: Hand-editing CITATION.cff during a release and accidentally dropping or reformatting the version key; a merge conflict resolved by deleting the key; committing a template CITATION.cff with placeholders.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13). Data as JSON: /api/errors/636881f847b3a382. Report an issue: GitHub.

Appendix: source

Thrown at sensor/tools/check_version.py:70

    if not package:
        raise SystemExit("[!] no [package] table found in %s" % CARGO)
    match = re.search(r"^version\s*=\s*\"([^\"]+)\"", package.group(1), re.M)
    if not match:
        raise SystemExit("[!] no version key in the [package] table of %s" % CARGO)
    return match.group(1)


def citation_version():
    """version: "3.0" from CITATION.cff.

    Nothing linked this to the tree, and it drifted: the file still claimed 3.0 while the code,
    the sensor and the published tag were all 3.1.1. That is not cosmetic - CITATION.cff exists
    so a paper can cite a specific version, and it had been quietly citing the wrong one.
    """

    match = re.search(r"^version\s*:\s*[\"']([^\"']+)[\"']", _read(CITATION), re.M)
    if not match:
        raise SystemExit("[!] no version key found in %s" % CITATION)
    return match.group(1)


def settings_gen_version():
    """pub const VERSION: &str = "3.2"; from the generated mirror of core/settings.py.

    This is a FOURTH place the version lives, and it was the one nobody checked here. The Rust
    parity test covers it, but that test needs a Rust toolchain - so the automated monthly bump,
    which is a text edit on a machine that has none, could not tell it had gone stale. It found
    out from a failed release: the tag was already pushed, the gate refused it, and nothing was
    built. A version bump is text; verifying it should be text too.
    """

    match = re.search(r'^pub const VERSION: &str = "([^"]+)";', _read(SETTINGS_GEN), re.M)
    if not match:
        raise SystemExit("[!] no VERSION constant found in %s" % SETTINGS_GEN)
    return match.group(1)

View on GitHub (pinned to 77cfb06d76)