{"id":"f15f5444e18b4985","repo":"pypa/pip","slug":"duplicate-entry-point","errorCode":null,"errorMessage":"Duplicate entry point","messagePattern":"Duplicate entry point","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pkg_resources/__init__.py","lineNumber":2827,"sourceCode":"        if req.specs:\n            raise ValueError\n        return req.extras\n\n    @classmethod\n    def parse_group(\n        cls,\n        group: str,\n        lines: _NestedStr,\n        dist: Distribution | None = None,\n    ):\n        \"\"\"Parse an entry point group\"\"\"\n        if not MODULE(group):\n            raise ValueError(\"Invalid group name\", group)\n        this: dict[str, Self] = {}\n        for line in yield_lines(lines):\n            ep = cls.parse(line, dist)\n            if ep.name in this:\n                raise ValueError(\"Duplicate entry point\", group, ep.name)\n            this[ep.name] = ep\n        return this\n\n    @classmethod\n    def parse_map(\n        cls,\n        data: str | Iterable[str] | dict[str, str | Iterable[str]],\n        dist: Distribution | None = None,\n    ):\n        \"\"\"Parse a map of entry point groups\"\"\"\n        _data: Iterable[tuple[str | None, str | Iterable[str]]]\n        if isinstance(data, dict):\n            _data = data.items()\n        else:\n            _data = split_sections(data)\n        maps: dict[str, dict[str, Self]] = {}\n        for group, lines in _data:\n            if group is None:","sourceCodeStart":2809,"sourceCodeEnd":2845,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pkg_resources/__init__.py#L2809-L2845","documentation":"Raised by EntryPoint.parse_group when two entry points within the same group share the same name (the 'name' left of '='). pkg_resources builds a dict keyed by entry point name per group, so duplicates are ambiguous and rejected with ValueError('Duplicate entry point', group, name).","triggerScenarios":"An entry_points.txt section lists the same key twice, e.g. '[console_scripts]\\nfoo=a:main\\nfoo=b:main', and pkg_resources parses that group via parse_group/parse_map.","commonSituations":"Merging entry_points from multiple packages that both define the same console script, a copy-paste error in metadata, or a packaging plugin that appends rather than replaces.","solutions":["Inspect entry_points.txt for the reported group and remove/rename the duplicate key so each name appears once.","If duplicates come from multiple installed distributions, uninstall or upgrade the conflicting package so only one defines that entry point.","Regenerate metadata from setup.cfg/pyproject.toml after de-duplicating the [project.scripts]/entry_points entries."],"exampleFix":"# before\n[console_scripts]\nfoo = pkg.a:main\nfoo = pkg.b:run\n\n# after\n[console_scripts]\nfoo = pkg.a:main\nbar = pkg.b:run","handlingStrategy":"validation","validationCode":"names = [ep.split('=', 1)[0].strip() for ep in lines if ep.strip()]\nif len(names) != len(set(names)):\n    dupes = {n for n in names if names.count(n) > 1}\n    raise ValueError(f'duplicate entry points: {dupes}')\nEntryPoint.parse_group(group, lines)","typeGuard":"def has_unique_names(entry_lines):\n    seen = set()\n    for ln in entry_lines:\n        if '=' in ln:\n            n = ln.split('=', 1)[0].strip()\n            if n in seen:\n                return False\n            seen.add(n)\n    return True","tryCatchPattern":"try:\n    EntryPoint.parse_group(group, lines)\nexcept ValueError as e:\n    if 'Duplicate entry point' in str(e):\n        # de-duplicate lines, then retry\n        ...\n    raise","preventionTips":["Maintain entry_points in pyproject.toml where the build backend enforces uniqueness.","Run a pre-publish check that asserts unique names per group."],"tags":["python","pkg-resources","entry-points","metadata","duplicate"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}