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
- Rename one of the colliding aliases (e.g. 'alexa' and 'alexb') so each normalized key is unique.
- If both lines are meant to be the same person, make their identities identical or delete the stale one.
- Merge identity updates into a single canonical entry instead of keeping old and new side by side under the same alias.
- 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
- Choose case-distinct aliases only after lowercasing — 'Alex' and 'alex' are the same key.
- One alias per human; update the existing entry when an identity changes instead of adding a sibling.
- Run the checker locally after every AUTHOR_MAP edit.
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
- {context}: expected 'Name <id+login@users.noreply.github.com
- {path}:{lineno}: expected 'alias = Name <email>'
- {context}: right-hand email must be numeric GitHub noreply,
- receipt {field} does not match the checked source
- ${label} contains duplicate checksum rows for ${name}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/5ae4da774995cb08.
Report an issue: GitHub.