{"record":{"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":"validation","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/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/pkg_resources/__init__.py#L3059-L3095","documentation":"Raised as UnknownExtra in Distribution.requires() at line 3077 when a requested extra name is not found in the dependency map (_dep_map). The code does `dm[safe_extra(ext)]` and catches KeyError, re-raising as UnknownExtra with the distribution and extra name. UnknownExtra is a subclass of Exception (not KeyError).","triggerScenarios":"Calling `dist.requires(['some_extra'])` where 'some_extra' is not defined in the package's metadata (requires.txt / METADATA Provides-Extra). Also triggered via EntryPoint.require() when the entry point references extras that don't exist.","commonSituations":"Requesting an extra that was misspelled or removed in a newer version; calling require() with extras that were never declared; version mismatch between expected and installed package extras; typo in extras name (e.g. 'all' vs 'ALL').","solutions":["Check the package's declared extras with `dist.extras` or inspect METADATA/requires.txt for valid extra names.","Correct the spelling/casing of the extra name (extras are case-insensitive but must match exactly otherwise).","Update to a version of the package that provides the extra.","Guard with try/except UnknownExtra before calling require()."],"exampleFix":"// before\ndist.requires(['feuture'])  # typo\n# UnknownExtra: mypackage 1.0 has no such extra feature 'feuture'\n\n// after\nvalid = set(dist.extras)\ndist.requires([e for e in ['feature'] if e in valid])","handlingStrategy":"validation","validationCode":"from pkg_resources import safe_extra\ndef filter_valid_extras(dist, requested_extras):\n    valid = set(dist.extras)\n    return [e for e in requested_extras if safe_extra(e) in valid]","typeGuard":"from pkg_resources import safe_extra\ndef extras_are_valid(dist, extras: list) -> bool:\n    valid = set(dist.extras)\n    return all(safe_extra(e) in valid for e in extras)\n","tryCatchPattern":"from pkg_resources import UnknownExtra\ntry:\n    reqs = dist.requires(['feature'])\nexcept UnknownExtra:\n    reqs = dist.requires()  # skip extras\n","preventionTips":["Check dist.extras before calling dist.requires() with extra names.","Use try/except UnknownExtra in plugin systems with optional extras.","Validate extra names against metadata to catch typos early."],"tags":["extras","pkg-resources","dependencies","metadata"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}