{"record":{"id":"e9776df032bcb8ff","repo":"caddyserver/caddy","slug":"replacement-d-for-header-field-s-v","errorCode":null,"errorMessage":"replacement %d for header field '%s': %v","messagePattern":"replacement (.+?) for header field '(.+?)': (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/headers/headers.go","lineNumber":154,"sourceCode":"\tif ops == nil {\n\t\treturn nil // it's possible no ops are configured; fix #6893\n\t}\n\tfor fieldName, replacements := range ops.Replace {\n\t\tfor i, r := range replacements {\n\t\t\tif r.SearchRegexp == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check if it contains placeholders\n\t\t\tif containsPlaceholders(r.SearchRegexp) {\n\t\t\t\t// Contains placeholders, skips precompilation, and recompiles at runtime\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Does not contain placeholders, safe to precompile\n\t\t\tre, err := regexp.Compile(r.SearchRegexp)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"replacement %d for header field '%s': %v\", i, fieldName, err)\n\t\t\t}\n\t\t\treplacements[i].re = re\n\t\t}\n\t}\n\treturn nil\n}\n\n// containsPlaceholders checks if the string contains Caddy placeholder syntax {key}\nfunc containsPlaceholders(s string) bool {\n\t_, after, ok := strings.Cut(s, \"{\")\n\tif !ok {\n\t\treturn false\n\t}\n\tcloseIdx := strings.Index(after, \"}\")\n\tif closeIdx == -1 {\n\t\treturn false\n\t}\n\t// Make sure there is content between the brackets","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/headers/headers.go#L136-L172","documentation":"Returned during HeaderOps.Provision while precompiling regex replacements: the replacement's search_regexp for a header field failed regexp.Compile. Placeholders like {http.request.uri} inside the regex are skipped (compiled at runtime), but a regex without placeholders must compile now — invalid regex syntax aborts provisioning.","triggerScenarios":"Configuring header > replace with a search_regexp containing invalid RE2 syntax, e.g. unbalanced parentheses, backreferences (\\1 — unsupported in RE2), or stray quantifiers; the error message includes the field name, replacement index, and compile error.","commonSituations":"Porting nginx sub_filter or Apache mod_substitute regexes that use PCRE-only features; forgetting Go uses RE2 (no lookaheads/backreferences); escaping mistakes through JSON config layers.","solutions":["Copy the exact regex from the error and test it with Go's regexp syntax, e.g. in a scratch Go program or an online RE2 tester.","Remove PCRE-only constructs: backreferences, lookahead/lookbehind; rewrite using RE2-compatible patterns.","Balance groups and escape literal parentheses/brackets.","Validate the whole config with `caddy validate` after fixing."],"exampleFix":"# before (PCRE backreference, invalid in RE2)\nreplace Host {\n    search_regexp \"^(www\\.)?(.+)$\"\n    replace \"example.com$1\"  # intended \\2 semantics\n}\n# after (RE2-safe capture groups)\nreplace Host {\n    search_regexp \"^(?:www\\.)?(.+)$\"\n    replace \"cdn.example.com${1}\"\n}","handlingStrategy":"validation","validationCode":"// Pre-flight in Go: compile every regex before shipping config\nfor field, reps := range cfg.Replace {\n    for i, r := range reps {\n        if r.SearchRegexp == \"\" { continue }\n        if _, err := regexp.Compile(r.SearchRegexp); err != nil {\n            return fmt.Errorf(\"field %s replacement %d: %w\", field, i, err)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Test header replacement regexes with Go's RE2 engine, not PCRE testers.","Avoid backreferences and lookarounds — unsupported in Go regexp.","`caddy validate` catches this at config load; make it a CI gate."],"tags":["caddy","headers","regex","re2","config-validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}