{"record":{"id":"182a6a79e2c67d23","repo":"stamparm/maltrail","slug":"s-expected-exactly-1-date-released-line-matched-d","errorCode":null,"errorMessage":"[!] %s: expected exactly 1 date-released line, matched %d","messagePattern":"\\[!\\] (.+?): expected exactly 1 date-released line, matched (.+?)","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"sensor/tools/bump_version.py","lineNumber":107,"sourceCode":"        new, n = re.subn(pattern, repl, text, flags=re.M)\n        # Exactly once. Zero means the file moved on and this script is now lying about\n        # covering it; more than once means the pattern is catching something it should not\n        # (a dependency's version key, say) and would corrupt the file.\n        if n != 1:\n            raise SystemExit(\"[!] %s: expected exactly 1 version line, matched %d\\n\"\n                             \"    Refusing to write ANY file - a half-applied bump is the \"\n                             \"failure this script exists to prevent.\" % (path, n))\n        planned.append((path, new, text != new))\n\n    if date_released:\n        path = os.path.join(ROOT, \"CITATION.cff\")\n        for i, (p, new, _) in enumerate(planned):\n            if p != path:\n                continue\n            out, n = re.subn(r'^(date-released\\s*:\\s*\")[^\"]*(\")',\n                             r'\\g<1>%s\\g<2>' % date_released, new, flags=re.M)\n            if n != 1:\n                raise SystemExit(\"[!] %s: expected exactly 1 date-released line, matched %d\" % (p, n))\n            planned[i] = (p, out, out != _read(p))\n\n    for path, new, changed in planned:\n        if changed:\n            with io.open(path, \"w\", encoding=\"utf8\") as f:\n                f.write(new)\n        print(\"[i] %-34s %s\" % (os.path.relpath(path, ROOT), \"updated\" if changed else \"already current\"))\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"set Maltrail's version in every file that carries it\")\n    parser.add_argument(\"version\", nargs=\"?\", help=\"the new version, e.g. 3.3\")\n    parser.add_argument(\"--next\", action=\"store_true\", help=\"bump the minor component of the current version\")\n    parser.add_argument(\"--check\", action=\"store_true\", help=\"verify only; write nothing\")\n    parser.add_argument(\"--date\", help=\"also set CITATION.cff date-released (YYYY-MM-DD, or 'today')\")\n    args = parser.parse_args()\n\n    if args.check:","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/sensor/tools/bump_version.py#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (CITATION.cff)\ndate-released: 2026-01-01\n// after\ndate-released: \"2026-09-12\"","handlingStrategy":"validation","validationCode":"import re\ntext = open('CITATION.cff').read()\nn = len(re.findall(r'^date-released\\s*:\\s*\"[^\"]*\"', text, re.M))\nif n != 1:\n    raise RuntimeError(f'CITATION.cff must contain exactly one quoted date-released line, found {n}')\n","typeGuard":"import re\ndef citation_date_ok(text: str) -> bool:\n    return len(re.findall(r'^date-released\\s*:\\s*\"[^\"]*\"', text, re.M)) == 1\n","tryCatchPattern":"try:\n    bump_version.main(['--version', '0.54', '--date', 'today'])\nexcept SystemExit as e:\n    if 'date-released' in str(e):\n        repair_citation_cff()\n","preventionTips":["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"],"tags":["versioning","citation","regex-match"],"backgroundTag":"invalid-config-value","analyzedSha":"77cfb06d7606506d101bbcec0786c77166c4255e","analyzedAt":"2026-09-13T03:50:16.010Z","contentChangedAt":"2026-09-13T03:50:16.010Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}