{"record":{"id":"89a6421ba8a838b1","repo":"coredns/coredns","slug":"the-rewrite-regex-pattern-s-uses-more-subexpres","errorCode":null,"errorMessage":"the rewrite regex pattern (%s) uses more subexpressions than its corresponding matching regex pattern (%s)","messagePattern":"the rewrite regex pattern \\((.+?)\\) uses more subexpressions than its corresponding matching regex pattern \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/rewrite/name.go","lineNumber":458,"sourceCode":"\tfor i := range 101 {\n\t\tif strings.Contains(s, \"{\"+strconv.Itoa(i)+\"}\") {\n\t\t\tsubExprUsage++\n\t\t}\n\t}\n\treturn subExprUsage\n}\n\n// isValidRegexPattern returns a regular expression for pattern matching or errors, if any.\nfunc isValidRegexPattern(rewriteFrom, rewriteTo string) (*regexp.Regexp, error) {\n\tif len(rewriteFrom) > maxRegexpLen {\n\t\treturn nil, fmt.Errorf(\"regex pattern too long: %d > %d\", len(rewriteFrom), maxRegexpLen)\n\t}\n\trewriteFromPattern, err := regexp.Compile(rewriteFrom)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid regex matching pattern: %s\", rewriteFrom)\n\t}\n\tif getSubExprUsage(rewriteTo) > rewriteFromPattern.NumSubexp() {\n\t\treturn nil, fmt.Errorf(\"the rewrite regex pattern (%s) uses more subexpressions than its corresponding matching regex pattern (%s)\", rewriteTo, rewriteFrom)\n\t}\n\treturn rewriteFromPattern, nil\n}\n","sourceCodeStart":440,"sourceCodeEnd":462,"githubUrl":"https://github.com/coredns/coredns/blob/558c9757a92b361e550bdba82d0b4ddf3d12d595/plugin/rewrite/name.go#L440-L462","documentation":"The replacement string may only reference as many subexpressions ({1}, {2}, ...) as the FROM pattern actually captures (regexp.NumSubexp). If getSubExprUsage(rewriteTo) exceeds that count, plugin setup fails because the rewrite could not fill the referenced groups.","triggerScenarios":"`rewrite stop name regex \\.a\\.com$ \\.b\\.com answer name \\.a\\.com$ {2}.c.com` — the TO side references {2} but the FROM pattern has fewer than 2 capture groups.","commonSituations":"Editing the FROM pattern to remove a capture group while the replacement still references it; copying replacement strings between rules with different patterns.","solutions":["Add the missing capture group(s) to the FROM pattern (wrap parts in parentheses)","Or lower the {N} references in the replacement to match existing groups","Recount capture groups carefully — non-capturing groups (?:...) do not count"],"exampleFix":"# before\nrewrite stop name regex (.*)\\.a\\.com {2}.b.com\n# after\nrewrite stop name regex (.*)\\.a\\.com {1}.b.com","handlingStrategy":"validation","validationCode":"func subexprCountOK(from, to string) bool {\n\tre, err := regexp.Compile(from)\n\tif err != nil { return false }\n\treturn subExprUsage(to) <= re.NumSubexp()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Recount capture groups whenever the FROM pattern changes","Remember (?:...) groups are non-capturing and cannot be referenced","Keep FROM and TO pairs reviewed together in code review"],"tags":["dns","coredns","regex","capture-group","rewrite-plugin"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"558c9757a92b361e550bdba82d0b4ddf3d12d595","analyzedAt":"2026-09-06T22:47:02.106Z","contentChangedAt":"2026-09-06T22:47:02.106Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}