ruvnet/RuView · error · ManifestError

duplicate marker ids: {sorted(dupes)}

Error message

duplicate marker ids: {sorted(dupes)}

What it means

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.

Source

Thrown at scripts/check_fix_markers.py:79


class ManifestError(Exception):
    pass


def load_manifest() -> dict:
    if not MANIFEST_PATH.exists():
        raise ManifestError(f"manifest not found: {MANIFEST_PATH}")
    try:
        data = json.loads(MANIFEST_PATH.read_text(encoding="utf-8"))
    except json.JSONDecodeError as e:
        raise ManifestError(f"manifest is not valid JSON: {e}") from e
    if not isinstance(data, dict) or not isinstance(data.get("markers"), list):
        raise ManifestError("manifest must be an object with a 'markers' array")
    ids = [m.get("id") for m in data["markers"]]
    dupes = {i for i in ids if ids.count(i) > 1}
    if dupes:
        raise ManifestError(f"duplicate marker ids: {sorted(dupes)}")
    return data


def _pattern_found(text: str, pattern: str) -> bool:
    if len(pattern) >= 2 and pattern.startswith("/") and pattern.endswith("/"):
        return re.search(pattern[1:-1], text, re.MULTILINE) is not None
    return pattern in text


def check_marker(marker: dict) -> tuple[bool, list[str]]:
    """Return (ok, problems) for a single marker."""
    problems: list[str] = []
    files = marker.get("files", [])
    require = marker.get("require", [])
    forbid = marker.get("forbid", [])

    if not files:
        problems.append("marker lists no files")

View on GitHub (pinned to 4685618388)

Solutions

  1. Grep the manifest for the duplicated id from the error message and rename or delete one entry
  2. Use issue-qualified unique ids (e.g. "RuView#396") as the existing entries do, so merges rarely collide
  3. If both entries are legitimate, merge their files/require/forbid lists into one marker with that id
  4. Re-run `python scripts/check_fix_markers.py` — exit code 0/1 means the manifest now parses

Example fix

# before (two markers share id)
{ "id": "RuView#396", "files": ["a.py"] },
{ "id": "RuView#396", "files": ["b.py"] }

# after
{ "id": "RuView#396", "files": ["a.py", "b.py"] },
{ "id": "RuView#531", "files": ["b.py"] }
Defensive patterns

Strategy: validation

Validate before calling

import json
from collections import Counter
from pathlib import Path

def manifest_ids_unique(path: str) -> bool:
    data = json.loads(Path(path).read_text(encoding="utf-8"))
    ids = [m.get("id") for m in data["markers"]]
    return not [i for i, n in Counter(ids).items() if n > 1]

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/5ecb592545b9a0e4. Report an issue: GitHub.