{"record":{"id":"51c962e2fe7eb88d","repo":"microsoft/playwright","slug":"invalid-glob-pattern-json-stringify-glob-nest","errorCode":null,"errorMessage":"Invalid glob pattern ${JSON.stringify(glob)}: nested '{' is not supported","messagePattern":"Invalid glob pattern (.+?): nested '\\{' is not supported","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/isomorphic/urlMatch.ts","lineNumber":68,"sourceCode":"        if (charAfter === '/') {\n          if (charBefore === '/')\n            tokens.push('((.+/)|)');\n          else\n            tokens.push('(.*/)');\n          ++i;\n        } else {\n          tokens.push('(.*)');\n        }\n      } else {\n        tokens.push('([^/]*)');\n      }\n      continue;\n    }\n\n    switch (c) {\n      case '{':\n        if (inGroup)\n          throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: nested '{' is not supported`);\n        inGroup = true;\n        tokens.push('(');\n        break;\n      case '}':\n        if (!inGroup)\n          throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: unmatched '}'`);\n        inGroup = false;\n        tokens.push(')');\n        break;\n      case ',':\n        if (inGroup) {\n          tokens.push('|');\n          break;\n        }\n        tokens.push('\\\\' + c);\n        break;\n      default:\n        tokens.push(escapedChars.has(c) ? '\\\\' + c : c);","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/isomorphic/urlMatch.ts#L50-L86","documentation":"Thrown by globToRegexPattern when a `{` is encountered while already inside a brace group (inGroup is true). The glob-to-regex converter supports single-level alternation `{a,b}` but does not support nesting, so a second `{` before the group closes is rejected.","triggerScenarios":"Passing a glob with nested alternation to urlMatches/route, e.g. `'{a,{b,c}}'`, `page.route('**/{foo,{bar,baz}}', ...)`, or `page.goto` baseURL glob with `{...{...}...}`. Triggered in the `case '{'` branch when inGroup is already true.","commonSituations":"Copying a shell/extglob pattern into a Playwright URL glob; attempting nested OR groups; building globs from templated fragments that double up braces.","solutions":["Flatten the alternation into a single level: `{a,b,c}` instead of `{a,{b,c}}`.","Split into multiple route handlers if true nesting semantics are required.","Switch to a RegExp match for complex alternation logic."],"exampleFix":"// before\npage.route('**/{api,{v1,v2}}/*', handler);  // nested brace\n\n// after\npage.route('**/{api,v1,v2}/*', handler);","handlingStrategy":"validation","validationCode":"function assertNoNestedBraces(glob: string) {\n  let depth = 0;\n  for (const c of glob) {\n    if (c === '{') depth++;\n    if (c === '}') depth--;\n    if (depth > 1) throw new Error(`Glob has nested braces: ${glob}`);\n    if (depth < 0) throw new Error(`Glob has unmatched }: ${glob}`);\n  }\n  if (depth !== 0) throw new Error(`Glob has unmatched {: ${glob}`);\n}","typeGuard":"function isFlatGlob(glob: string): boolean {\n  let depth = 0;\n  for (const c of glob) {\n    if (c === '{') depth++;\n    else if (c === '}') depth--;\n    if (depth > 1) return false;\n  }\n  return depth === 0;\n}","tryCatchPattern":"try {\n  page.route(glob, handler);\n} catch (e) {\n  if (/nested '\\{' is not supported/.test(e.message)) {\n    glob = flattenAlternation(glob); // user-supplied flattener\n    page.route(glob, handler);\n  } else throw e;\n}","preventionTips":["Keep glob alternation to a single level.","Use RegExp for nested OR logic.","Add a unit test for any glob builder that interpolates lists."],"tags":["glob","url-matching","parsing","validation"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}