pypa/pip · error · ValueError
invalid glob %r: mismatching set marker '{' or '}'
Error message
invalid glob %r: mismatching set marker '{' or '}' What it means
Raised by iglob() when brace set markers '{' and '}' are mismatched (matched by _CHECK_MISMATCH_SET). distlib supports brace expansion like '{src,tests}/*.py' but rejects patterns with an unmatched '}' at the start or an unmatched '{' with no closing '}', raising ValueError 'mismatching set marker'.
Source
Thrown at src/pip/_vendor/distlib/util.py:1441
#
# Glob functionality
#
RICH_GLOB = re.compile(r'\{([^}]*)\}')
_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]')
_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$')
def iglob(path_glob):
"""Extended globbing function that supports ** and {opt1,opt2,opt3}."""
if _CHECK_RECURSIVE_GLOB.search(path_glob):
msg = """invalid glob %r: recursive glob "**" must be used alone"""
raise ValueError(msg % path_glob)
if _CHECK_MISMATCH_SET.search(path_glob):
msg = """invalid glob %r: mismatching set marker '{' or '}'"""
raise ValueError(msg % path_glob)
return _iglob(path_glob)
def _iglob(path_glob):
rich_path_glob = RICH_GLOB.split(path_glob, 1)
if len(rich_path_glob) > 1:
assert len(rich_path_glob) == 3, rich_path_glob
prefix, set, suffix = rich_path_glob
for item in set.split(','):
for path in _iglob(''.join((prefix, item, suffix))):
yield path
else:
if '**' not in path_glob:
for item in std_iglob(path_glob):
yield item
else:
prefix, radical = path_glob.split('**', 1)
if prefix == '':View on GitHub (pinned to d7d0d0a394)
Solutions
- Balance the braces: 'src/{a,b}/*.py'.
- If you did not intend a set, remove the stray '{' or '}'.
- Count '{' and '}' in the pattern and ensure they are equal and properly nested.
Example fix
// before
list(iglob('src/{a,b/*.py'))
// after
list(iglob('src/{a,b}/*.py')) Defensive patterns
Strategy: validation
Validate before calling
def safe_iglob(pattern):
if pattern.count('{') != pattern.count('}'):
raise ValueError('unbalanced brace set markers: %r' % pattern)
from distlib.util import iglob
return list(iglob(pattern)) Try / catch
from distlib.util import iglob
try:
matches = list(iglob(pattern))
except ValueError as e:
if 'mismatching set marker' in str(e):
pattern = pattern.replace('{', '').replace('}', '') # or fix brackets
matches = list(iglob(pattern))
else:
raise Prevention
- Ensure '{' and '}' are balanced in glob patterns.
- Build brace sets programmatically and add the closing brace in the same step.
- Validate brace balance before invoking iglob().
When it happens
Trigger: iglob('src/{a,b/*.py') (missing '}'), iglob('src/a,b}/x') (missing '{'), or any pattern where braces are unbalanced.
Common situations: Programmatic glob construction that omits a brace, copy-paste from configs that stripped a brace, or escaping mistakes.
Related errors
- invalid glob %r: recursive glob "**" must be used alone
- {req_name} does not appear to be a Python project: neither '
- Directory {name!r} is not installable. Neither 'setup.py' no
- Invalid requirement: {req_as_string!r}: {exc}
- Invalid requirement: {req_string!r}: {exc}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/fb6116844a3110b6.json.
Report an issue: GitHub.