pypa/pip · error · ValueError
Duplicate group name
Error message
Duplicate group name
What it means
Raised as ValueError in EntryPoint.parse_map at line 2851 when the same group name appears more than once in the entry points metadata. After stripping, if a group is already in the `maps` dict, the second occurrence is rejected because merging would be ambiguous.
Solutions
- Merge the duplicate sections into a single section with all entries.
- Remove the redundant section header so each group appears exactly once.
- Regenerate entry_points.txt via reinstall or setup.py egg_info.
- Audit the build process that creates entry_points.txt for append-instead-of-replace bugs.
Example fix
// before: entry_points.txt // [console_scripts] // a = pkg:run // [console_scripts] // b = pkg:other // after // [console_scripts] // a = pkg:run // b = pkg:other
Defensive patterns
Strategy: validation
Validate before calling
def merge_duplicate_sections(text: str) -> str:
from collections import OrderedDict
sections = OrderedDict()
current = None
for line in text.strip().splitlines():
s = line.strip()
if s.startswith('[') and s.endswith(']'):
current = s
sections.setdefault(current, [])
elif current:
sections[current].append(line)
return '\n'.join(k + '\n' + '\n'.join(v) for k, v in sections.items()) Type guard
def has_unique_sections(text: str) -> bool:
import re
headers = re.findall(r'^\[(.+)\]$', text, re.MULTILINE)
return len(headers) == len(set(headers))
Try / catch
from pkg_resources import EntryPoint
try:
ep_map = EntryPoint.parse_map(raw_text)
except ValueError as e:
if 'Duplicate group' in str(e):
ep_map = EntryPoint.parse_map(merge_duplicate_sections(raw_text))
else:
raise
Prevention
- Merge duplicate section headers into a single section in entry_points.txt.
- Audit metadata generation tools for append-instead-of-replace bugs.
- Regenerate entry_points.txt after fixing.
When it happens
Trigger: An entry_points.txt file with two '[console_scripts]' sections, or two identical section headers after stripping whitespace. parse_map iterates sections and checks `if group in maps`.
Common situations: Concatenating multiple metadata fragments that repeat section headers; manual editing that duplicates a section; build tools that append to rather than replace entry_points.txt.
Related errors
- Duplicate entry point
- Invalid group name
- Entry point %r not found
- Entry points must be listed in groups
- EntryPoint must be in 'name=module:attrs [extras]' format
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/1cd213457f6547b8.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/pkg_resources/__init__.py:2851
cls,
data: str | Iterable[str] | dict[str, str | Iterable[str]],
dist: Distribution | None = None,
):
"""Parse a map of entry point groups"""
_data: Iterable[tuple[str | None, str | Iterable[str]]]
if isinstance(data, dict):
_data = data.items()
else:
_data = split_sections(data)
maps: dict[str, dict[str, Self]] = {}
for group, lines in _data:
if group is None:
if not lines:
continue
raise ValueError("Entry points must be listed in groups")
group = group.strip()
if group in maps:
raise ValueError("Duplicate group name", group)
maps[group] = cls.parse_group(group, lines, dist)
return maps
def _version_from_file(lines):
"""
Given an iterable of lines from a Metadata file, return
the value of the Version field, if present, or None otherwise.
"""
def is_version_line(line):
return line.lower().startswith('version:')
version_lines = filter(is_version_line, lines)
line = next(iter(version_lines), '')
_, _, value = line.partition(':')
return safe_version(value.strip()) or None
View on GitHub (pinned to f399c37189)