{"record":{"id":"82282b6bcdc0e293","repo":"pypa/pip","slug":"invalid-group-name","errorCode":null,"errorMessage":"Invalid group name","messagePattern":"Invalid group name","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pkg_resources/__init__.py","lineNumber":2822,"sourceCode":"    @classmethod\n    def _parse_extras(cls, extras_spec):\n        if not extras_spec:\n            return ()\n        req = Requirement.parse('x' + extras_spec)\n        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()","sourceCodeStart":2804,"sourceCodeEnd":2840,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/pkg_resources/__init__.py#L2804-L2840","documentation":"Raised as ValueError in EntryPoint.parse_group when the group name fails the MODULE regex (`\\w+(\\.\\w+)*$`). Group names must be valid dotted Python identifiers (e.g. 'console_scripts', 'myapp.commands'). Invalid characters or empty names trigger this at line 2821-2822.","triggerScenarios":"Calling EntryPoint.parse_group(group, lines) with a group containing hyphens, spaces, special characters, or other invalid identifier characters. Also fires when entry_points.txt has a malformed section header like [my-group] (hyphens not allowed).","commonSituations":"Using hyphens instead of underscores or dots in group names in entry_points.txt; typos in section headers; custom plugin group names that don't follow Python identifier conventions.","solutions":["Use only word characters and dots in group names: 'console_scripts', 'myapp.plugins', 'pytest11'.","Replace hyphens with underscores in group names.","Validate group names with `re.match(r'\\w+(\\.\\w+)*$', group)` before parsing.","Check the section header in entry_points.txt / setup.cfg for invalid characters."],"exampleFix":"// before: entry_points.txt\n// [my-plugin-group]\n// entry = mypkg:main\n# ValueError: Invalid group name 'my-plugin-group'\n\n// after\n// [my_plugin_group]\n// entry = mypkg:main","handlingStrategy":"validation","validationCode":"import re\nMODULE = re.compile(r'\\w+(\\.\\w+)*$').match\ndef is_valid_group_name(group: str) -> bool:\n    return bool(MODULE(group))","typeGuard":"import re\ndef is_valid_group(name: str) -> bool:\n    return bool(re.match(r'^\\w+(\\.\\w+)*$', name)) and len(name) > 0\n","tryCatchPattern":"from pkg_resources import EntryPoint\ntry:\n    result = EntryPoint.parse_group(group, lines)\nexcept ValueError:\n    group = group.replace('-', '_')\n    result = EntryPoint.parse_group(group, lines)\n","preventionTips":["Use only word characters and dots in entry point group names.","Replace hyphens with underscores in group names in metadata.","Validate group names before parsing entry point metadata."],"tags":["entry-points","pkg-resources","group-name","validation"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}