{"record":{"id":"5ecb592545b9a0e4","repo":"ruvnet/RuView","slug":"duplicate-marker-ids-sorted-dupes","errorCode":null,"errorMessage":"duplicate marker ids: {sorted(dupes)}","messagePattern":"duplicate marker ids: (.+?)","errorType":"validation","errorClass":"ManifestError","httpStatus":null,"severity":"error","filePath":"scripts/check_fix_markers.py","lineNumber":79,"sourceCode":"\n\nclass ManifestError(Exception):\n    pass\n\n\ndef load_manifest() -> dict:\n    if not MANIFEST_PATH.exists():\n        raise ManifestError(f\"manifest not found: {MANIFEST_PATH}\")\n    try:\n        data = json.loads(MANIFEST_PATH.read_text(encoding=\"utf-8\"))\n    except json.JSONDecodeError as e:\n        raise ManifestError(f\"manifest is not valid JSON: {e}\") from e\n    if not isinstance(data, dict) or not isinstance(data.get(\"markers\"), list):\n        raise ManifestError(\"manifest must be an object with a 'markers' array\")\n    ids = [m.get(\"id\") for m in data[\"markers\"]]\n    dupes = {i for i in ids if ids.count(i) > 1}\n    if dupes:\n        raise ManifestError(f\"duplicate marker ids: {sorted(dupes)}\")\n    return data\n\n\ndef _pattern_found(text: str, pattern: str) -> bool:\n    if len(pattern) >= 2 and pattern.startswith(\"/\") and pattern.endswith(\"/\"):\n        return re.search(pattern[1:-1], text, re.MULTILINE) is not None\n    return pattern in text\n\n\ndef check_marker(marker: dict) -> tuple[bool, list[str]]:\n    \"\"\"Return (ok, problems) for a single marker.\"\"\"\n    problems: list[str] = []\n    files = marker.get(\"files\", [])\n    require = marker.get(\"require\", [])\n    forbid = marker.get(\"forbid\", [])\n\n    if not files:\n        problems.append(\"marker lists no files\")","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/scripts/check_fix_markers.py#L61-L97","documentation":"load_manifest() in scripts/check_fix_markers.py collects the 'id' of every entry in the markers array and raises ManifestError listing any id that appears more than once (sorted). Ids are the stable keys used by --only filtering and CI reporting, so duplicates would make marker selection and regression attribution ambiguous.","triggerScenarios":"Copy-pasting an existing marker block to add a new fix and forgetting to change its id; a git merge that brings the same marker in on both branches; renaming a marker's id in one place while an old entry with that id survives elsewhere in the file.","commonSituations":"Parallel branches each adding a marker with the same auto-generated id; a bot or script appending markers without checking for existing ids; cherry-picks that duplicate entries.","solutions":["Grep the manifest for the duplicated id from the error message and rename or delete one entry","Use issue-qualified unique ids (e.g. \"RuView#396\") as the existing entries do, so merges rarely collide","If both entries are legitimate, merge their files/require/forbid lists into one marker with that id","Re-run `python scripts/check_fix_markers.py` — exit code 0/1 means the manifest now parses"],"exampleFix":"# before (two markers share id)\n{ \"id\": \"RuView#396\", \"files\": [\"a.py\"] },\n{ \"id\": \"RuView#396\", \"files\": [\"b.py\"] }\n\n# after\n{ \"id\": \"RuView#396\", \"files\": [\"a.py\", \"b.py\"] },\n{ \"id\": \"RuView#531\", \"files\": [\"b.py\"] }","handlingStrategy":"validation","validationCode":"import json\nfrom collections import Counter\nfrom pathlib import Path\n\ndef manifest_ids_unique(path: str) -> bool:\n    data = json.loads(Path(path).read_text(encoding=\"utf-8\"))\n    ids = [m.get(\"id\") for m in data[\"markers\"]]\n    return not [i for i, n in Counter(ids).items() if n > 1]","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive marker ids from issue numbers (RuView#NNN) so concurrent branches rarely collide","Grep for an id before adding a marker with it: grep '\"id\": \"RuView#396\"' scripts/fix-markers.json","Merge duplicate entries' file lists instead of keeping two markers with one id"],"tags":["manifest","duplicates","ci","json","python","scripts"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}