stamparm/maltrail · error · SystemExit
[!] no VERSION assignment in core/settings.py
Error message
[!] no VERSION assignment in core/settings.py
What it means
bump_version.py reads the current version by regex-matching a top-level `VERSION = "x.y"` assignment in core/settings.py. If the regex finds no match, it aborts with this SystemExit. It throws because the tool cannot safely compute the next version without a canonical two-component VERSION assignment.
Solutions
- Open core/settings.py and restore a top-level two-component assignment like VERSION = "0.5".
- Check the file path: the script resolves core/settings.py relative to its ROOT, so run it from a checkout that actually contains core/settings.py.
- If the variable was renamed or quoted differently, either rename it back or update the regex in current() to match the new format.
Example fix
// before (core/settings.py) MALTRAIL_VERSION = '0.5' // after VERSION = "0.5"
Defensive patterns
Strategy: validation
Validate before calling
import re
text = open('core/settings.py').read()
if not re.search(r'^VERSION\s*=\s*"([^"]+)"', text, re.M):
raise RuntimeError('core/settings.py lacks a VERSION = "x.y" assignment')
Type guard
def has_version_assignment(text: str) -> bool:
return re.search(r'^VERSION\s*=\s*"([^"]+)"', text, re.M) is not None
Try / catch
try:
bump_version.main(['--next'])
except SystemExit as e:
if 'no VERSION assignment' in str(e):
fix_settings_version_file()
Prevention
- Keep VERSION as the first line of core/settings.py with double quotes
- Add a CI check that greps for the VERSION assignment before running release tooling
- Never rename or re-quote the VERSION variable without updating bump_version.py
When it happens
Trigger: Running `python sensor/tools/bump_version.py --next` (or --version) when core/settings.py has no line starting with `VERSION = "..."` (exact spacing/name per regex `^VERSION\s*=\s*"([^"]+)"` in multiline mode).
Common situations: A refactor renamed the variable (e.g. CURRENT_VERSION), switched to single quotes, moved the version into a config file/pyproject.toml, added a comment prefix before VERSION, or core/settings.py is missing/stale in a build checkout.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- [!] : expected exactly 1 version line, matched Refusing to…
- [!] : expected exactly 1 date-released line, matched
- [!] no VERSION assignment found in
- [!] cannot bump %r - expected 'major.minor'
- [!] %r is not 'major.minor' - Maltrail versions two…
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/f223cd5c54778cc3.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/tools/bump_version.py:72
r'^(VERSION\s*=\s*")[^"]*(")', r'\g<1>%s\g<2>' % version),
(os.path.join(ROOT, "sensor", "Cargo.toml"),
r'^(version\s*=\s*")[^"]*(")', r'\g<1>%s\g<2>' % cargo),
# anchored to the package entry: a bare ^version in a lock file would match every
# dependency in it
(os.path.join(ROOT, "sensor", "Cargo.lock"),
r'(name = "maltrail-sensor"\nversion = ")[^"]*(")', r'\g<1>%s\g<2>' % cargo),
(os.path.join(ROOT, "CITATION.cff"),
r'^(version\s*:\s*")[^"]*(")', r'\g<1>%s\g<2>' % version),
(os.path.join(ROOT, "sensor", "src", "settings_gen.rs"),
r'^(pub const VERSION: &str = ")[^"]*(";)', r'\g<1>%s\g<2>' % version),
]
def current():
match = re.search(r'^VERSION\s*=\s*"([^"]+)"',
_read(os.path.join(ROOT, "core", "settings.py")), re.M)
if not match:
raise SystemExit("[!] no VERSION assignment in core/settings.py")
return match.group(1)
def next_minor(version):
parts = version.split(".")
if len(parts) < 2 or not all(p.isdigit() for p in parts[:2]):
raise SystemExit("[!] cannot bump %r - expected 'major.minor'" % version)
return "%s.%d" % (parts[0], int(parts[1]) + 1)
def apply(version, date_released=None):
"""Rewrite every file, or none of them."""
planned = []
for path, pattern, repl in _edits(version):
text = _read(path)
new, n = re.subn(pattern, repl, text, flags=re.M)
# Exactly once. Zero means the file moved on and this script is now lying aboutView on GitHub (pinned to 77cfb06d76)