microsoft/playwright · error · Error
Invalid glob pattern ${JSON.stringify(glob)}: unmatched '}'
Error message
Invalid glob pattern ${JSON.stringify(glob)}: unmatched '}' What it means
Thrown by globToRegexPattern when a `}` is encountered while not inside a brace group (inGroup is false). It indicates an unbalanced closing brace with no matching opening `{`, which the converter cannot turn into a valid regex.
Source
Thrown at packages/isomorphic/urlMatch.ts:74
} else {
tokens.push('(.*)');
}
} else {
tokens.push('([^/]*)');
}
continue;
}
switch (c) {
case '{':
if (inGroup)
throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: nested '{' is not supported`);
inGroup = true;
tokens.push('(');
break;
case '}':
if (!inGroup)
throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: unmatched '}'`);
inGroup = false;
tokens.push(')');
break;
case ',':
if (inGroup) {
tokens.push('|');
break;
}
tokens.push('\\' + c);
break;
default:
tokens.push(escapedChars.has(c) ? '\\' + c : c);
}
}
if (inGroup)
throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: unmatched '{'`);
tokens.push('$');
return tokens.join('');View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Add the matching opening `{` or remove the stray `}`.
- Escape the brace if it is literal: `\}`.
- Reconstruct the glob from known-good parts and log it before registering the route.
Example fix
// before
page.route('**/api}', handler); // unmatched }
// after
page.route('**/api', handler); // or '**/\}' for literal brace Defensive patterns
Strategy: validation
Validate before calling
function assertBracesBalanced(glob: string) {
let depth = 0;
for (const c of glob) {
if (c === '{') depth++;
else if (c === '}') depth--;
if (depth < 0) throw new Error(`Glob has unmatched }: ${glob}`);
}
if (depth !== 0) throw new Error(`Glob has unmatched {: ${glob}`);
} Type guard
function hasBalancedBraces(glob: string): boolean {
let depth = 0;
for (const c of glob) {
if (c === '{') depth++;
else if (c === '}') depth--;
if (depth < 0) return false;
}
return depth === 0;
} Try / catch
try {
page.route(glob, handler);
} catch (e) {
if (/unmatched '\}'/.test(e.message)) {
glob = glob.replace(/(^|[^{])}/g, '$1\\}'); // escape stray brace
page.route(glob, handler);
} else throw e;
} Prevention
- Escape literal braces with `\{`/`\}`.
- Log dynamically built globs before registration.
- Reject brace imbalance at config-load time.
When it happens
Trigger: Passing a glob with a stray `}`, e.g. `'**/api}'`, `page.route('**/foo,bar}', ...)`, or any glob where `}` appears without a preceding `{`. Triggered in the `case '}'` branch when inGroup is false.
Common situations: Typo in a URL glob; truncation that drops the opening brace; JSON/templating that injects a stray closing brace; mis-pasting a pattern fragment.
Related errors
- Invalid glob pattern ${JSON.stringify(glob)}: nested '{' is
- Invalid glob pattern ${JSON.stringify(glob)}: unmatched '{'
- Error while parsing selector `${selector}` - selector cannot
- url parameter should be string, RegExp, URLPattern or functi
- Unsupported token "${unsupportedToken.toSource()}" while par
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/04a5deef4c061f3d.
Report an issue: GitHub.