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
- Open CITATION.cff and ensure exactly one quoted date-released line, e.g. date-released: "2026-09-12".
- 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.
- 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
- Always keep date-released quoted in CITATION.cff
- Regenerate CITATION.cff with the date-released field intact after tooling updates
- Include CITATION.cff format checks in release CI
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
- [!] no VERSION assignment in core/settings.py
- [!] : expected exactly 1 version line, matched Refusing to…
- [!] cannot bump %r - expected 'major.minor'
- [!] %r is not 'major.minor' - Maltrail versions two…
- [!] no VERSION assignment found in
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)