{"id":"439b81e94083b47a","repo":"pypa/pip","slug":"invalid-module-name","errorCode":null,"errorMessage":"Invalid module name","messagePattern":"Invalid module name","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pkg_resources/__init__.py","lineNumber":2693,"sourceCode":"    )?\n    \"\"\",\n    re.VERBOSE | re.IGNORECASE,\n).match\n\n\nclass EntryPoint:\n    \"\"\"Object representing an advertised importable object\"\"\"\n\n    def __init__(\n        self,\n        name: str,\n        module_name: str,\n        attrs: Iterable[str] = (),\n        extras: Iterable[str] = (),\n        dist: Distribution | None = None,\n    ):\n        if not MODULE(module_name):\n            raise ValueError(\"Invalid module name\", module_name)\n        self.name = name\n        self.module_name = module_name\n        self.attrs = tuple(attrs)\n        self.extras = tuple(extras)\n        self.dist = dist\n\n    def __str__(self):\n        s = \"%s = %s\" % (self.name, self.module_name)\n        if self.attrs:\n            s += ':' + '.'.join(self.attrs)\n        if self.extras:\n            s += ' [%s]' % ','.join(self.extras)\n        return s\n\n    def __repr__(self):\n        return \"EntryPoint.parse(%r)\" % str(self)\n\n    @overload","sourceCodeStart":2675,"sourceCodeEnd":2711,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pkg_resources/__init__.py#L2675-L2711","documentation":"Raised as ValueError by EntryPoint.__init__ when module_name fails the MODULE regex (`\\w+(\\.\\w+)*$`). Module names must consist of word characters (letters, digits, underscore) and dotted segments; any other character (hyphen, slash, space, leading dot) is rejected. Note the error message is exactly 'Invalid module name' with the offending value as the second argument.","triggerScenarios":"Constructing an EntryPoint(name, module_name, ...) directly with a module_name containing invalid characters — most commonly a hyphenated project name used verbatim as a module ('my-pkg.app') instead of the underscored import name ('my_pkg.app').","commonSituations":"Auto-generating entry points from PyPI project names (which allow hyphens) without normalizing to the import name; typos in entry_points.txt; programmatic EntryPoint creation from untrusted/user input.","solutions":["Normalize the module name before constructing the EntryPoint: replace '-' with '_' (and any other non-word char) to match Python's import identifier rules.","Validate with the same regex first: `if MODULE(module_name): EntryPoint(...)` (MODULE = re.compile(r'\\w+(\\.\\w+)*$').match).","Build EntryPoints via EntryPoint.parse() from a well-formed 'name=module:attr' string, which applies the same validation through its pattern."],"exampleFix":"// before\nep = EntryPoint('cli', 'my-pkg.cli', ['main'])  # ValueError: Invalid module name\n\n// after\nmodule_name = 'my-pkg.cli'.replace('-', '_')\nep = EntryPoint('cli', module_name, ['main'])  # 'my_pkg.cli' — OK","handlingStrategy":"validation","validationCode":"import re\nMODULE = re.compile(r'\\w+(\\.\\w+)*$').match\n\ndef safe_entry_point(name, module_name, attrs=()):\n    if not MODULE(module_name):\n        # normalize hyphens and other common project-name chars\n        module_name = re.sub(r'[^\\w.]', '_', module_name)\n        if not MODULE(module_name):\n            raise ValueError(f'Invalid module name: {module_name!r}')\n    from pkg_resources import EntryPoint\n    return EntryPoint(name, module_name, attrs)","typeGuard":"import re\nMODULE = re.compile(r'\\w+(\\.\\w+)*$').match\n\ndef is_valid_module_name(name: str) -> bool:\n    return isinstance(name, str) and bool(MODULE(name))","tryCatchPattern":"try:\n    ep = EntryPoint(name, module_name, attrs)\nexcept ValueError as e:\n    if 'Invalid module name' in str(e):\n        module_name = module_name.replace('-', '_')\n        ep = EntryPoint(name, module_name, attrs)\n    else:\n        raise","preventionTips":["Normalize project names (replace '-' with '_') before using as a module name.","Validate module_name with the MODULE regex before constructing EntryPoint.","Build EntryPoints via parse() from a well-formed 'name=module:attr' string."],"tags":["pkg-resources","entry-point","validation","module-name","regex"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}