Hmbown/CodeWhale · error · ValueError

{path}:{lineno}: duplicate alias {alias!r}

Error message

{path}:{lineno}: duplicate alias {alias!r}

What it means

Aliases in AUTHOR_MAP normalize case-insensitively (norm_key); when the same normalized alias maps to two different identities, the checker raises this duplicate-alias error with the path, line, and alias. It prevents ambiguous resolution when the checker later matches trailers and commit identities back to canonical humans.

Source

Thrown at scripts/check-coauthor-trailers.py:154

        raise ValueError(
            f"{context}: right-hand email must be numeric GitHub noreply, got {identity.email}"
        )
    return identity


def load_author_map(path: Path) -> dict[str, Identity]:
    aliases: dict[str, Identity] = {}
    for lineno, raw_line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
        line = raw_line.split("#", 1)[0].strip()
        if not line:
            continue
        if "=" not in line:
            raise ValueError(f"{path}:{lineno}: expected 'alias = Name <email>'")
        alias, raw_identity = [part.strip() for part in line.split("=", 1)]
        identity = parse_identity(raw_identity, f"{path}:{lineno}")
        key = norm_key(alias)
        if key in aliases and aliases[key] != identity:
            raise ValueError(f"{path}:{lineno}: duplicate alias {alias!r}")
        aliases[key] = identity
        aliases.setdefault(norm_key(identity.email), identity)
        aliases.setdefault(norm_key(identity.name), identity)
        if login := github_login_from_noreply(identity.email):
            aliases.setdefault(norm_key(login), identity)
    return aliases


def git_log(commit_range: str) -> list[Commit]:
    try:
        raw = subprocess.check_output(
            [
                "git",
                "log",
                "--format=%H%x00%P%x00%an%x00%ae%x00%s%x00%B%x1e",
                commit_range,
            ],
            cwd=ROOT,

View on GitHub (pinned to 8880682c63)

Solutions

  1. Rename one of the colliding aliases (e.g. 'alexa' and 'alexb') so each normalized key is unique.
  2. If both lines are meant to be the same person, make their identities identical or delete the stale one.
  3. Merge identity updates into a single canonical entry instead of keeping old and new side by side under the same alias.
  4. Re-run the checker; it fails fast at map-load time before any git history is scanned.

Example fix

# before
alex = Alex A <111+alexa@users.noreply.github.com>
Alex = Alex B <222+alexb@users.noreply.github.com>
# after
alexa = Alex A <111+alexa@users.noreply.github.com>
alexb = Alex B <222+alexb@users.noreply.github.com>
Defensive patterns

Strategy: validation

Validate before calling

def norm_key(s: str) -> str:
    return s.strip().lower()

def map_has_no_alias_collisions(path) -> bool:
    seen = {}
    for line in path.read_text().splitlines():
        line = line.split("#", 1)[0].strip()
        if not line or "=" not in line:
            continue
        alias, ident = (p.strip() for p in line.split("=", 1))
        key = norm_key(alias)
        if key in seen and seen[key] != ident:
            return False
        seen[key] = ident
    return True

Prevention

When it happens

Trigger: Lines like 'alex = Alex A <111+alexa@...>' and later 'Alex = Alex B <222+alexb@...>' — norm_key('alex') collides and the stored Identity differs. Note the reverse-dictionary entries (by email, name, login) use setdefault, so only explicit alias collisions with differing identities raise.

Common situations: Two contributors both mapped as 'alex'; adding a new entry whose alias collides with an existing name-key; case differences ('Jane' vs 'jane') that normalize to the same key; duplicate entries for someone who changed their email, mapping both old and new identities under the same alias with a different target.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/5ae4da774995cb08. Report an issue: GitHub.