pypa/pip · error · DistlibException
Invalid specification
Error message
Invalid specification '%s'
What it means
Raised as DistlibException by distlib.util.get_export_entry when the specification string fails to match ENTRY_RE (the 'name = module:attr [flags]' export grammar) AND contains an unbalanced or stray '[' or ']'. Because the regex requires well-formed optional flags, a leftover bracket signals a malformed flags section rather than a simply-unknown format. The function returns None (no error) when the spec is unparseable but contains no brackets.
Solutions
- Ensure the spec matches 'name = module.path:attribute [flag=value,...]' with balanced brackets.
- Remove stray '[' / ']' characters that are not part of a flags block.
- Validate entry-point strings with packaging.entry_points or importlib.metadata before passing to get_export_entry.
Example fix
# before
get_export_entry('run = mod:main [console_scripts')
# after
get_export_entry('run = mod:main [console_scripts]') Defensive patterns
Strategy: validation
Validate before calling
from distlib.util import ENTRY_RE
def valid_export_spec(spec):
return bool(ENTRY_RE.search(spec)) and spec.count('[') == spec.count(']') Type guard
def is_balanced_brackets(s: str) -> bool:
return isinstance(s, str) and s.count('[') == s.count(']') Try / catch
from distlib.util import DistlibException
try:
get_export_entry(spec)
except DistlibException as e:
if 'Invalid specification' in str(e):
fix_brackets(spec) Prevention
- Validate entry-point strings with importlib.metadata.
- Keep flags block as a single trailing '[...]'.
When it happens
Trigger: get_export_entry('cli = mod:main [bad flag spec'), get_export_entry('name = mod:attr extra['), or any entry-point spec where '[' or ']' appears but the whole string doesn't match the ENTRY_RE grammar (e.g. unbalanced brackets, spaces breaking the regex).
Common situations: Hand-editing entry_points strings in setup.py/setup.cfg; metadata export lists generated by a tool that malformed the flags field; legacy entry point syntax with stray brackets.
Related errors
- Error parsing entry points for
- Error parsing entry points for
- Ill-formed name/version string
- Badly formatted data
- Duplicate entry point
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/4b4ced204a131d72.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_vendor/distlib/util.py:729
and self.flags == other.flags)
return result
__hash__ = object.__hash__
ENTRY_RE = re.compile(
r'''(?P<name>([^\[]\S*))
\s*=\s*(?P<callable>(\w+)([:\.]\w+)*)
\s*(\[\s*(?P<flags>[\w-]+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])?
''', re.VERBOSE)
def get_export_entry(specification):
m = ENTRY_RE.search(specification)
if not m:
result = None
if '[' in specification or ']' in specification:
raise DistlibException("Invalid specification "
"'%s'" % specification)
else:
d = m.groupdict()
name = d['name']
path = d['callable']
colons = path.count(':')
if colons == 0:
prefix, suffix = path, None
else:
if colons != 1:
raise DistlibException("Invalid specification "
"'%s'" % specification)
prefix, suffix = path.split(':')
flags = d['flags']
if flags is None:
if '[' in specification or ']' in specification:
raise DistlibException("Invalid specification "
"'%s'" % specification)View on GitHub (pinned to f399c37189)