{"record":{"id":"f0556b833ae091fe","repo":"pypa/pip","slug":"invalid-egg-fragment","errorCode":"invalid-egg-fragment","errorMessage":"The '{fragment}' egg fragment is invalid","messagePattern":"The '(.+?)' egg fragment is invalid","errorType":"exception","errorClass":"InvalidEggFragment","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/models/link.py","lineNumber":526,"sourceCode":"        return urllib.parse.urlunsplit((scheme, netloc, path, query, \"\"))\n\n    _egg_fragment_re = re.compile(r\"[#&]egg=([^&]*)\")\n\n    # Per PEP 508.\n    _project_name_re = re.compile(\n        r\"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$\", re.IGNORECASE\n    )\n\n    def _egg_fragment(self) -> str | None:\n        match = self._egg_fragment_re.search(self._url)\n        if not match:\n            return None\n\n        # An egg fragment looks like a PEP 508 project name, along with\n        # an optional extras specifier. Anything else is invalid.\n        project_name = match.group(1)\n        if not self._project_name_re.match(project_name):\n            raise InvalidEggFragment(self, project_name)\n\n        return project_name\n\n    _subdirectory_fragment_re = re.compile(r\"[#&]subdirectory=([^&]*)\")\n\n    @property\n    def subdirectory_fragment(self) -> str | None:\n        match = self._subdirectory_fragment_re.search(self._url)\n        if not match:\n            return None\n        return match.group(1)\n\n    def metadata_link(self) -> Link | None:\n        \"\"\"Return a link to the associated core metadata file (if any).\"\"\"\n        if self.metadata_file_data is None:\n            return None\n        metadata_url = f\"{self.url_without_fragment}.metadata\"\n        if self.metadata_file_data.hashes is None:","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/models/link.py#L508-L544","documentation":"Raised as InvalidEggFragment when a URL's '#egg=...' fragment does not parse as a valid PEP 508 project name. In link.py the captured egg fragment is matched against '^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$' (case-insensitive); any deviation (version specifiers, extras, leading digit-only, punctuation) is rejected. This guards legacy VCS/direct-URL installs that still rely on the egg fragment to identify the project.","triggerScenarios":"Calling pip install with a VCS or direct URL containing '#egg=' followed by a token that fails the PEP 508 project-name regex, e.g. '#egg=pkg>=1.0', '#egg=pkg[extra]', '#egg=1pkg', '#egg=pkg!='. Accessing Link.egg_fragment / the _egg_fragment() private method on such a Link triggers it.","commonSituations":"Copy-pasted install commands from outdated docs that stuff version specifiers or extras into the egg fragment; migrating old requirements.txt lines that used '#egg=name==1.0'; shell quoting that lets a comparison operator leak into the fragment.","solutions":["Remove any version specifier or extras from the egg fragment so it is a bare project name: '#egg=pkg'.","Prefer the modern direct-URL requirement syntax 'pkg @ git+https://...' which replaces the egg fragment entirely.","For extras, use 'pkg[extra] @ git+https://...' rather than placing '[extra]' inside the egg fragment.","Validate the fragment against the PEP 508 name regex before passing the URL to pip."],"exampleFix":"# before\npip install \"git+https://github.com/o/r.git#egg=pkg>=1.0\"\n\n# after\npip install \"pkg @ git+https://github.com/o/r.git\"","handlingStrategy":"validation","validationCode":"import re\nfrom urllib.parse import urlsplit\n\n_PROJECT_NAME_RE = re.compile(r\"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$\", re.I)\n\ndef valid_egg_fragment(url: str) -> bool:\n    frag = urlsplit(url).fragment\n    for pair in frag.split(\"&\"):\n        if pair.startswith(\"egg=\"):\n            name = pair[len(\"egg=\"):]\n            return bool(_PROJECT_NAME_RE.match(name))\n    return True  # no egg fragment present\n\n# assert valid_egg_fragment(\"git+https://o/r.git#egg=pkg\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer the direct-URL requirement syntax 'name @ url' over egg fragments.","Never place version specifiers or extras inside the #egg= fragment.","Validate fragments with the PEP 508 name regex before passing URLs to pip."],"tags":["packaging","vcs-install","pep508","url-fragment"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}