caddyserver/caddy · error
compiling regular expression %d: %v
Error message
compiling regular expression %d: %v
What it means
The rewrite handler compiles each path_regexp pattern with Go's regexp.Compile at provision time; this error wraps a compile failure and includes the 0-based index of the offending entry. Go's RE2 syntax differs from PCRE, so patterns valid in nginx or Perl (backreferences, lookaheads) fail here. The error is fatal at config load.
Source
Thrown at modules/caddyhttp/rewrite/rewrite.go:116
// CaddyModule returns the Caddy module information.
func (Rewrite) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "http.handlers.rewrite",
New: func() caddy.Module { return new(Rewrite) },
}
}
// Provision sets up rewr.
func (rewr *Rewrite) Provision(ctx caddy.Context) error {
rewr.logger = ctx.Logger()
for i, rep := range rewr.PathRegexp {
if rep.Find == "" {
return fmt.Errorf("path_regexp find cannot be empty")
}
re, err := regexp.Compile(rep.Find)
if err != nil {
return fmt.Errorf("compiling regular expression %d: %v", i, err)
}
rep.re = re
}
if rewr.Query != nil {
for _, replacementOp := range rewr.Query.Replace {
err := replacementOp.Provision(ctx)
if err != nil {
return fmt.Errorf("compiling regular expression %s in query rewrite replace operation: %v", replacementOp.SearchRegexp, err)
}
}
}
return nil
}
func (rewr Rewrite) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
const message = "rewrote request"View on GitHub (pinned to 50e54ee279)
Solutions
- Read the wrapped regexp error — it names the exact syntax problem and position
- Replace PCRE-only constructs: drop lookaheads/backreferences, rewrite with capture groups used via {re.match.1} placeholders
- Double-check backslash escaping in JSON/Caddyfile ("\\d" in JSON for \d)
- Test the pattern standalone: echo 'pattern' in Go regexp tester or 'go run' a snippet with regexp.Compile
Example fix
// before
"path_regexp": [{ "find": "/old(/", "replace": "/new" }]
// after
"path_regexp": [{ "find": "/old(/", "replace": "/new" }] // balanced: "/old(/" -> "/old(/"
// concretely: "find": "/old/(.*)", "replace": "/new/{re.match.1}" Defensive patterns
Strategy: validation
Validate before calling
for i, rep := range rewriteCfg.PathRegexp {
if _, err := regexp.Compile(rep.Find); err != nil {
return fmt.Errorf("path_regexp[%d] has invalid regex %q: %w", i, rep.Find, err)
}
} Prevention
- Test regexes with Go (RE2) semantics, not PCRE testers
- Remember lookaheads, lookbehinds and backreferences are unsupported
- Escape backslashes correctly for JSON (double them)
When it happens
Trigger: A path_regexp 'find' containing invalid RE2 syntax: unbalanced parentheses like "(/old", bad escapes like "\d+" written as "\d+" in JSON without proper quoting, or PCRE-only constructs like "(?=foo)" or "(a)\1".
Common situations: Porting nginx rewrite rules (lookaheads/backreferences) to Caddy, JSON escaping mistakes where the regex loses its backslashes, or using { } quantifiers that clash with Caddy placeholder syntax without escaping.
Related errors
- compiling regexp for mapping %d: %v
- compiling matcher regexp %s: %v
- path_regexp find cannot be empty
- compiling regular expression %s in query rewrite replace ope
- replacement %d for header field '%s': %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/c61ebf9892a97f13.
Report an issue: GitHub.