stamparm/maltrail · error · SystemExit

[!] : expected exactly 1 date-released line, matched

Error message

[!] %s: expected exactly 1 date-released line, matched %d

What it means

When a --date is supplied, apply() rewrites the date-released field in CITATION.cff using re.subn and requires exactly one match. If the citation file's date-released line is missing, renamed, or duplicated, the script exits instead of writing a half-updated citation.

Solutions

  1. Open CITATION.cff and ensure exactly one quoted date-released line, e.g. date-released: "2026-09-12".
  2. If your tooling writes an unquoted YAML date, update the regex in apply() to accept both forms or normalize the file to the quoted form.
  3. Remove duplicate date-released entries if the file was merged or duplicated.

Example fix

// before (CITATION.cff)
date-released: 2026-01-01
// after
date-released: "2026-09-12"
Defensive patterns

Strategy: validation

Validate before calling

import re
text = open('CITATION.cff').read()
n = len(re.findall(r'^date-released\s*:\s*"[^"]*"', text, re.M))
if n != 1:
    raise RuntimeError(f'CITATION.cff must contain exactly one quoted date-released line, found {n}')

Type guard

import re
def citation_date_ok(text: str) -> bool:
    return len(re.findall(r'^date-released\s*:\s*"[^"]*"', text, re.M)) == 1

Try / catch

try:
    bump_version.main(['--version', '0.54', '--date', 'today'])
except SystemExit as e:
    if 'date-released' in str(e):
        repair_citation_cff()

Prevention

When it happens

Trigger: Running a bump with --date (or date=='today') when CITATION.cff has no `date-released: "..."` line, uses unquoted YAML date format, or contains more than one date-released entry.

Common situations: CITATION.cff was regenerated by a tool that dropped or reformatted date-released (e.g. `date-released: 2024-01-15` without quotes); manual edits duplicated the field; file removed during repo cleanup.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at sensor/tools/bump_version.py:107

        new, n = re.subn(pattern, repl, text, flags=re.M)
        # Exactly once. Zero means the file moved on and this script is now lying about
        # covering it; more than once means the pattern is catching something it should not
        # (a dependency's version key, say) and would corrupt the file.
        if n != 1:
            raise SystemExit("[!] %s: expected exactly 1 version line, matched %d\n"
                             "    Refusing to write ANY file - a half-applied bump is the "
                             "failure this script exists to prevent." % (path, n))
        planned.append((path, new, text != new))

    if date_released:
        path = os.path.join(ROOT, "CITATION.cff")
        for i, (p, new, _) in enumerate(planned):
            if p != path:
                continue
            out, n = re.subn(r'^(date-released\s*:\s*")[^"]*(")',
                             r'\g<1>%s\g<2>' % date_released, new, flags=re.M)
            if n != 1:
                raise SystemExit("[!] %s: expected exactly 1 date-released line, matched %d" % (p, n))
            planned[i] = (p, out, out != _read(p))

    for path, new, changed in planned:
        if changed:
            with io.open(path, "w", encoding="utf8") as f:
                f.write(new)
        print("[i] %-34s %s" % (os.path.relpath(path, ROOT), "updated" if changed else "already current"))


def main():
    parser = argparse.ArgumentParser(description="set Maltrail's version in every file that carries it")
    parser.add_argument("version", nargs="?", help="the new version, e.g. 3.3")
    parser.add_argument("--next", action="store_true", help="bump the minor component of the current version")
    parser.add_argument("--check", action="store_true", help="verify only; write nothing")
    parser.add_argument("--date", help="also set CITATION.cff date-released (YYYY-MM-DD, or 'today')")
    args = parser.parse_args()

    if args.check:

View on GitHub (pinned to 77cfb06d76)