pypa/pip · error · ValueError

Duplicate entry point

Error message

Duplicate entry point

What it means

Raised as ValueError in EntryPoint.parse_group at line 2826-2827 when the same entry point name appears more than once within a single group. The dict `this` tracks seen names; a collision means metadata is ambiguous and cannot be resolved deterministically.

Solutions

  1. Search the entry_points.txt / setup.cfg / pyproject.toml for duplicate names within the same group and remove the stale entry.
  2. If you need multiple targets, use different entry point names for each.
  3. Reinstall the package after fixing the metadata so entry_points.txt is regenerated.
  4. Audit generated entry_points.txt in the .egg-info directory for duplicates.

Example fix

// before: setup.cfg
// [options.entry_points]
// console_scripts =
//     mycli = mypkg:main
//     mycli = otherpkg:run

// after
// [options.entry_points]
// console_scripts =
//     mycli = mypkg:main
Defensive patterns

Strategy: validation

Validate before calling

def deduplicate_entry_points(lines):
    seen = set()
    result = []
    for line in lines:
        name = line.split('=')[0].strip()
        if name not in seen:
            seen.add(name)
            result.append(line)
    return result

Type guard

def has_no_duplicate_names(lines: list[str]) -> bool:
    names = [l.split('=')[0].strip() for l in lines if '=' in l]
    return len(names) == len(set(names))

Try / catch

from pkg_resources import EntryPoint
try:
    group_map = EntryPoint.parse_group('console_scripts', lines)
except ValueError as e:
    if 'Duplicate' in str(e):
        # deduplicate and retry
        group_map = EntryPoint.parse_group('console_scripts', deduplicate_entry_points(lines))
    else:
        raise

Prevention

When it happens

Trigger: An entry_points.txt or setup.cfg [entry_points] section lists two lines with the same left-hand name under the same group. For example, two 'cli = ...' lines under [console_scripts].

Common situations: Merging entry point lists from multiple sources that both define the same name; copy-paste duplication; refactoring that leaves stale entries alongside new ones; automated generation tools that don't deduplicate.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/f15f5444e18b4985. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_vendor/pkg_resources/__init__.py:2827

        if req.specs:
            raise ValueError
        return req.extras

    @classmethod
    def parse_group(
        cls,
        group: str,
        lines: _NestedStr,
        dist: Distribution | None = None,
    ):
        """Parse an entry point group"""
        if not MODULE(group):
            raise ValueError("Invalid group name", group)
        this: dict[str, Self] = {}
        for line in yield_lines(lines):
            ep = cls.parse(line, dist)
            if ep.name in this:
                raise ValueError("Duplicate entry point", group, ep.name)
            this[ep.name] = ep
        return this

    @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:

View on GitHub (pinned to f399c37189)