caddyserver/caddy · error
compiling regular expression
Error message
compiling regular expression %s in query rewrite replace operation: %v
What it means
Wrapper error produced while provisioning the query-rewrite section of the rewrite handler. It surfaces when any query replace operation's Provision fails; the %s shows the operation's SearchRegexp so you can identify which regex is broken. The underlying cause is almost always the nested 'replacement for query field' regexp compile error.
Solutions
- Note the search_regexp printed in the message and validate it with Go's RE2 syntax
- Fix or remove the invalid search_regexp for that query key
- Escape backslashes correctly in JSON
- Run 'caddy validate' after editing
Example fix
// before
"query": { "replace": [{ "key": "q", "search_regexp": "[", "replace": "x" }] }
// after
"query": { "replace": [{ "key": "q", "search_regexp": "\\[\\d+\\]", "replace": "x" }] } Defensive patterns
Strategy: validation
Validate before calling
for _, op := range rewriteCfg.Query.Replace {
if op.SearchRegexp != "" {
if _, err := regexp.Compile(op.SearchRegexp); err != nil {
return fmt.Errorf("query replace for %q has invalid regex: %w", op.Key, err)
}
}
} Prevention
- Keep query rewrite regexes trivial (anchors + character classes)
- Prefer search_replace literal matching when a regex is not required
- Validate configs in CI with 'caddy validate'
When it happens
Trigger: Config with rewrite.query.replace[] where search_regexp is set to an invalid RE2 pattern, e.g. "[" or "(?i" (unterminated).
Common situations: Adding query-parameter rewriting with copy-pasted regexes from other tools, or JSON escaping issues that corrupt the pattern.
Related errors
- compiling regular expression
- path_regexp find cannot be empty
- replacement for query field
- compiling matcher regexp
- compiling regexp for mapping
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/119f155b4fe7beea.
Report an issue: GitHub.
Appendix: source
Thrown at modules/caddyhttp/rewrite/rewrite.go:124
// 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"
c := rewr.logger.Check(zap.DebugLevel, message)
if c == nil {
rewr.Rewrite(r, repl)
return next.ServeHTTP(w, r)
}
changed := rewr.Rewrite(r, repl)View on GitHub (pinned to 50e54ee279)