denoland/deno · error

Capturing groups are not allowed at {}.

Error message

Capturing groups are not allowed at {}.

What it means

cli/lsp/path_to_regex.rs:170: inside a placeholder's custom pattern, an inner '(' bumps the group counter; if the character after it is not '?', the group is a capturing group, which path-to-regexp forbids because the token model already captures each placeholder itself. The error reports the offset (index + pattern length) of the offending '('.

Source

Thrown at cli/lsp/path_to_regex.rs:170

            pattern.push(chars.next().unwrap());
            pattern.push(
              chars
                .next()
                .ok_or_else(|| anyhow!("Unexpected termination of string."))?,
            );
            continue;
          }
          if next_char == Some(&')') {
            count -= 1;
            if count == 0 {
              chars.next();
              break;
            }
          } else if next_char == Some(&'(') {
            count += 1;
            pattern.push(chars.next().unwrap());
            if chars.peek() != Some(&'?') {
              return Err(anyhow!(
                "Capturing groups are not allowed at {}.",
                index + pattern.len()
              ));
            }
            continue;
          }

          pattern.push(chars.next().unwrap());
        }

        if count > 0 {
          return Err(anyhow!("Unbalanced pattern at {}.", index));
        }
        if pattern.is_empty() {
          return Err(anyhow!("Missing pattern at {}.", index));
        }
        let pattern_len = pattern.len();
        tokens.push(LexToken {

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Convert inner groups to non-capturing: "/x/:pkg((?:\\d+))", "/x/:file((?:foo|bar))"
  2. Audit every '(' inside patterns and add '?:' unless it starts a group construct like (?= or (?! which already begin with '?'
  3. Test the schema against path-to-regexp before publishing the registry config

Example fix

// before
{ "schema": "/x/:pkg((\\d+))" }

// after
{ "schema": "/x/:pkg((?:\\d+))" }
Defensive patterns

Strategy: validation

Validate before calling

function hasCapturingGroup(pattern: string): boolean {
  let depth = 0;
  for (let i = 0; i < pattern.length; i++) {
    const c = pattern[i];
    if (c === "\\") { i++; continue; }
    if (c === "(" && pattern[i + 1] !== "?") return true;
  }
  return false;
}

Prevention

When it happens

Trigger: A schema pattern with a capture group: "/x/:pkg((\\d+))" or "/x/:file((foo|bar))"; alternations written without '?:'.

Common situations: Registry authors pasting ordinary regex (which uses capturing groups freely) into the pattern slot; refactoring from string-to-regex code that relied on capture indices.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/401974959596fb32. Report an issue: GitHub.