{"id":"75712b5502be8b7d","repo":"pypa/pip","slug":"s-has-no-such-extra-feature-r","errorCode":null,"errorMessage":"%s has no such extra feature %r","messagePattern":"(.+?) has no such extra feature %r","errorType":"exception","errorClass":"UnknownExtra","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pkg_resources/__init__.py","lineNumber":3077,"sourceCode":"        return dm\n\n    def _build_dep_map(self):\n        dm = {}\n        for name in 'requires.txt', 'depends.txt':\n            for extra, reqs in split_sections(self._get_metadata(name)):\n                dm.setdefault(extra, []).extend(parse_requirements(reqs))\n        return dm\n\n    def requires(self, extras: Iterable[str] = ()):\n        \"\"\"List of Requirements needed for this distro if `extras` are used\"\"\"\n        dm = self._dep_map\n        deps: list[Requirement] = []\n        deps.extend(dm.get(None, ()))\n        for ext in extras:\n            try:\n                deps.extend(dm[safe_extra(ext)])\n            except KeyError as e:\n                raise UnknownExtra(\n                    \"%s has no such extra feature %r\" % (self, ext)\n                ) from e\n        return deps\n\n    def _get_metadata_path_for_display(self, name):\n        \"\"\"\n        Return the path to the given metadata file, if available.\n        \"\"\"\n        try:\n            # We need to access _get_metadata_path() on the provider object\n            # directly rather than through this class's __getattr__()\n            # since _get_metadata_path() is marked private.\n            path = self._provider._get_metadata_path(name)\n\n        # Handle exceptions e.g. in case the distribution's metadata\n        # provider doesn't support _get_metadata_path().\n        except Exception:\n            return '[could not detect]'","sourceCodeStart":3059,"sourceCodeEnd":3095,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pkg_resources/__init__.py#L3059-L3095","documentation":"Raised as UnknownExtra (a ResolutionError subclass) from Distribution.requires() when an extras name passed in is not present in the distribution's dependency map. The message formats the distribution and the offending extra so you can see which package was queried and which extra it does not declare.","triggerScenarios":"Calling dist.requires(['some_extra']) where 'some_extra' is not listed in the distribution's 'Provides-Extra' metadata / requires.txt extra sections; dm[safe_extra(ext)] raises KeyError which is wrapped into UnknownExtra.","commonSituations":"Typos in the extra name (e.g. 'tests' vs 'test'), requesting an extra the installed version no longer provides, or depending on an extra from a different package version than expected.","solutions":["Check the distribution's metadata (pip show <pkg>, or its METADATA 'Provides-Extra' lines) for the exact extra names it supports.","Correct the extra name spelling/casing in your call to requires().","Upgrade or downgrade the package to a version that declares the extra you need."],"exampleFix":"# before\ndist.requires(['tsets'])  # typo -> UnknownExtra\n\n# after\nextra = 'tests' if 'tests' in dist.extras else None\nif extra:\n    dist.requires([extra])","handlingStrategy":"validation","validationCode":"extras = [e for e in requested_extras if e in dist.extras]\nmissing = set(requested_extras) - set(extras)\nif missing:\n    raise ValueError(f'extras not provided by {dist}: {missing}')\ndist.requires(extras)","typeGuard":"def extra_is_provided(dist, extra: str) -> bool:\n    return extra in getattr(dist, 'extras', set())","tryCatchPattern":"try:\n    dist.requires([extra])\nexcept pkg_resources.UnknownExtra as e:\n    # log and continue without that extra\n    ...","preventionTips":["Read dist.extras before calling requires().","Derive extra names from the package's METADATA 'Provides-Extra' rather than guessing."],"tags":["python","pkg-resources","extras","packaging"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}