pypa/pip · error · ValueError
Entry points must be listed in groups
Error message
Entry points must be listed in groups
What it means
Raised as ValueError in EntryPoint.parse_map at line 2848 when entry point lines appear before any group section header. The split_sections function returns (None, content) for lines before the first '[group]'; if content exists under section=None, it means orphaned lines with no group context.
Solutions
- Ensure every entry point line is preceded by a '[group_name]' section header in entry_points.txt.
- Add the missing section header at the top of the file.
- Regenerate the .egg-info/entry_points.txt by reinstalling or running setup.py egg_info.
- Validate metadata files before packaging.
Example fix
// before: entry_points.txt // mycli = mypkg:main // [console_scripts] // other = otherpkg:run // after // [console_scripts] // mycli = mypkg:main // other = otherpkg:run
Defensive patterns
Strategy: validation
Validate before calling
def ensure_group_header(text: str) -> str:
lines = text.strip().splitlines()
if lines and not lines[0].strip().startswith('['):
lines.insert(0, '[console_scripts]')
return '\n'.join(lines) Type guard
def all_lines_under_sections(text: str) -> bool:
in_section = False
for line in text.strip().splitlines():
stripped = line.strip()
if stripped.startswith('['):
in_section = True
elif stripped and '=' in stripped and not in_section:
return False
return True
Try / catch
from pkg_resources import EntryPoint
try:
ep_map = EntryPoint.parse_map(raw_text)
except ValueError as e:
if 'must be listed in groups' in str(e):
ep_map = EntryPoint.parse_map(ensure_group_header(raw_text))
else:
raise
Prevention
- Ensure entry_points.txt always starts with a '[group]' section header.
- Validate metadata files before packaging.
- Regenerate entry_points.txt via reinstall if hand-edited.
When it happens
Trigger: An entry_points.txt file that has lines before the first '[group]' section header, or a multi-line string passed to parse_map without a leading section. The check `if group is None` with non-empty lines triggers the error.
Common situations: Truncated or hand-edited entry_points.txt missing the section header; copy-paste that drops the '[console_scripts]' line; metadata generation tools that emit raw lines first.
Related errors
- Duplicate entry point
- Error parsing entry points for
- Invalid section heading
- Duplicate group name
- Entry point %r not found
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/c4babf714461d33a.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/pkg_resources/__init__.py:2848
@classmethod
def parse_map(
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), '')View on GitHub (pinned to f399c37189)