alibaba/nacos · error · IllegalArgumentException

The number of capturing groups in the pattern segment {patte

Error message

The number of capturing groups in the pattern segment {pattern} does not match the number of URI template variables it defines, which can occur if capturing groups are used in a URI template regex. Use non-capturing groups instead.

What it means

AntPathMatcher throws this when matching a URI-template pattern whose compiled regex has a different number of capturing groups than the count of named variables it extracted from the template. Each `{var}` placeholder becomes one variable and is expected to correspond to exactly one capturing group. Introducing extra capturing groups (e.g. `(a|b)` inside a regex segment) desynchronizes the two counts, so the matcher refuses to bind values rather than silently assign them to the wrong variable.

Source

Thrown at common/src/main/java/com/alibaba/nacos/common/packagescan/resource/AntPathMatcher.java:598

                return "";
            }
            return Pattern.quote(s.substring(start, end));
        }

        /**
         * Main entry point.
         *
         * @return {@code true} if the string matches against the pattern, or {@code false} otherwise.
         */
        public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
            if (this.exactMatch) {
                return this.caseSensitive ? this.rawPattern.equals(str) : this.rawPattern.equalsIgnoreCase(str);
            } else if (this.pattern != null) {
                Matcher matcher = this.pattern.matcher(str);
                if (matcher.matches()) {
                    if (uriTemplateVariables != null) {
                        if (this.variableNames.size() != matcher.groupCount()) {
                            throw new IllegalArgumentException("The number of capturing groups in the pattern segment "
                                    + this.pattern + " does not match the number of URI template variables it defines, "
                                    + "which can occur if capturing groups are used in a URI template regex. "
                                    + "Use non-capturing groups instead.");
                        }
                        for (int i = 1; i <= matcher.groupCount(); i++) {
                            String name = this.variableNames.get(i - 1);
                            if (name.startsWith("*")) {
                                throw new IllegalArgumentException("Capturing patterns (" + name + ") are not "
                                        + "supported by the AntPathMatcher. Use the PathPatternParser instead.");
                            }
                            String value = matcher.group(i);
                            uriTemplateVariables.put(name, value);
                        }
                    }
                    return true;
                }
            }
            return false;

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Replace every capturing group `( ... )` inside the regex segment with a non-capturing group `(?: ... )` so the group count stays equal to the number of `{var}` placeholders.
  2. Count the `{var}` placeholders in your pattern and confirm that number equals the capturing-group count of the compiled regex; reduce groups until they match.
  3. If you need richer capture semantics, switch off AntPathMatcher and use PathPatternParser instead (as the message suggests).
  4. Unit-test the pattern with extractUriTemplateVariables against a sample path before deploying it to a config/mapping table.

Example fix

// before
String pattern = "/api/{version:[0-9]+(\\.[0-9]+)}/items";
// the inner (...) is a capturing group, adding one beyond {version}

// after
String pattern = "/api/{version:[0-9]+(?:\\.[0-9]+)}/items";
// non-capturing group keeps groupCount == 1 == variableNames.size()
Defensive patterns

Strategy: validation

Validate before calling

// Validate before matching: count placeholders == capturing groups
static void assertPatternBalanced(String pattern) {
    int placeholders = 0;
    boolean inRegex = false;
    for (int i = 0; i < pattern.length(); i++) {
        char c = pattern.charAt(i);
        if (c == '{') { placeholders++; inRegex = true; }
        else if (c == '}') { inRegex = false; }
    }
    // recompile the regex portions and assert groupCount == placeholders per segment
    // reject patterns with unbalanced capturing groups early
}

Prevention

When it happens

Trigger: Calling AntPathMatcher.doMatch (or extractUriTemplateVariables) with a pattern string that embeds a custom regex containing capturing parentheses, e.g. `/api/{version:[0-9]+(\\.[0-9]+)}` where the inner `(...)` adds an extra group beyond the one `{version}` implies. The error fires only on the matching branch that populates uriTemplateVariables (this.pattern != null and exactMatch is false).

Common situations: Migrating Spring URL patterns into Nacos's internal AntPathMatcher (a vendored Spring copy). Hand-writing path patterns with alternation or grouping. Copying regex from an external source that uses unescaped capturing groups. Confusing Spring's PathPatternParser syntax (which allows groups) with the stricter AntPathMatcher contract.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/606b46892a2b4876. Report an issue: GitHub.