{"record":{"id":"71954df826628fd0","repo":"zloirock/core-js","slug":"invalid-capture-group-name","errorCode":null,"errorMessage":"Invalid capture group name","messagePattern":"Invalid capture group name","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"packages/core-js/modules/es.regexp.constructor.js","lineNumber":115,"sourceCode":"    } else if (chr === ']') {\n      brackets = false;\n    } else if (!brackets) switch (true) {\n      case chr === '[':\n        brackets = true;\n        break;\n      case chr === '(':\n        result += chr;\n        if (exec(IS_NCG, stringSlice(string, index + 1))) {\n          index += 2;\n          ncg = true;\n          groupid++;\n        } else if (charAt(string, index + 1) !== '?') {\n          groupid++;\n        }\n        continue;\n      case chr === '>' && ncg:\n        if (groupname === '' || hasOwn(names, groupname)) {\n          throw new SyntaxError('Invalid capture group name');\n        }\n        names[groupname] = true;\n        named[named.length] = [groupname, groupid];\n        ncg = false;\n        groupname = '';\n        continue;\n    }\n    if (ncg) groupname += chr;\n    else result += chr;\n  }\n  // convert `\\k<name>` backreferences to numbered backreferences\n  for (var ni = 0; ni < named.length; ni++) {\n    var backref = '\\\\k<' + named[ni][0] + '>';\n    var numRef = '\\\\' + named[ni][1];\n    while (stringIndexOf(result, backref) > -1) {\n      result = replace(result, backref, numRef);\n    }\n  } return [result, named];","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/zloirock/core-js/blob/84e45fba098dd3a177d5cf2247d06ab8e98d3790/packages/core-js/modules/es.regexp.constructor.js#L97-L133","documentation":"The RegExp constructor polyfill supports named capture groups. When parsing a pattern containing a named group (?<name>...), it validates that the name is non-empty and not already used. A duplicate or empty name raises a SyntaxError at construction time, matching ES2018 spec validation performed natively by modern engines.","triggerScenarios":"new RegExp('(?<a>x)(?<a>y)', flags) — duplicate group name; pattern like '(?<x>...)' where the polyfill's manual scan ends with an empty groupname; duplicate names across alternations '(?<year>\\d{4})|(?<year>\\d{2})'; running the same pattern twice after concatenating fragments that each declare the same name.","commonSituations":"Building regexes dynamically by concatenating pattern fragments that share group names; porting regexes from other languages (PCRE allows duplicate names with different backrefs); polyfilled environments (older browsers/Node) where native RegExp would have rejected earlier with a slightly different message; copy-pasting two regexes and merging their named groups.","solutions":["Rename one of the duplicate capture groups so every (?<name>) in the pattern is unique.","Check for empty or malformed names: use only IdentifierPart chars and ensure a name follows '?<'.","If merging patterns, wrap fragments in non-capturing groups and rename colliding groups programmatically.","Test on the target environment — on modern engines the native RegExp throws the same class of SyntaxError earlier, so fix the pattern at the source."],"exampleFix":"// before\nconst re = new RegExp('(?<year>\\\\d{4})-(?<year>\\\\d{2})'); // SyntaxError\n// after\nconst re = new RegExp('(?<year>\\\\d{4})-(?<month>\\\\d{2})');","handlingStrategy":"validation","validationCode":"function validateGroupNames(pattern) {\n  const names = [...pattern.matchAll(/\\(\\?<([^>]+)>/g)].map(m => m[1]);\n  const dup = names.filter((n, i) => names.indexOf(n) !== i);\n  if (dup.length || names.some(n => !n)) throw new SyntaxError('Invalid capture group name in: ' + pattern);\n}\nvalidateGroupNames(pattern); const re = new RegExp(pattern);","typeGuard":"function hasUniqueNamedGroups(pattern) {\n  const names = [...pattern.matchAll(/\\(\\?<([^>]+)>/g)].map(m => m[1]);\n  return new Set(names).size === names.length && !names.includes('');\n}\n// usage: if (hasUniqueNamedGroups(pattern)) new RegExp(pattern);","tryCatchPattern":"let re;\ntry {\n  re = new RegExp(pattern);\n} catch (e) {\n  if (e instanceof SyntaxError && /capture group/.test(e.message)) {\n    // fall back to unnamed groups or log pattern for manual fix\n  } else throw e;\n}","preventionTips":["Keep named groups unique per pattern, including across alternations.","When concatenating pattern fragments, namespace group names or use non-capturing groups.","Test regex construction on the oldest supported browser where core-js polyfill is active.","Extract group names with matchAll to validate before building RegExp."],"tags":["javascript","polyfill","regexp","syntaxerror"],"backgroundTag":"invalid-capture-group-name","analyzedSha":"84e45fba098dd3a177d5cf2247d06ab8e98d3790","analyzedAt":"2026-08-30T20:36:10.323Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}