{"record":{"id":"4823ef85830a1aa3","repo":"caddyserver/caddy","slug":"compiling-regexp-for-mapping-d-v","errorCode":null,"errorMessage":"compiling regexp for mapping %d: %v","messagePattern":"compiling regexp for mapping (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/map/map.go","lineNumber":80,"sourceCode":"}\n\n// Provision sets up h.\nfunc (h *Handler) Provision(_ caddy.Context) error {\n\tfor j, dest := range h.Destinations {\n\t\tif strings.Count(dest, \"{\") != 1 || !strings.HasPrefix(dest, \"{\") {\n\t\t\treturn fmt.Errorf(\"destination must be a placeholder and only a placeholder\")\n\t\t}\n\t\th.Destinations[j] = strings.Trim(dest, \"{}\")\n\t}\n\n\tfor i, m := range h.Mappings {\n\t\tif m.InputRegexp == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tvar err error\n\t\th.Mappings[i].re, err = regexp.Compile(m.InputRegexp)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"compiling regexp for mapping %d: %v\", i, err)\n\t\t}\n\t}\n\n\t// TODO: improve efficiency even further by using an actual map type\n\t// for the non-regexp mappings, OR sort them and do a binary search\n\n\treturn nil\n}\n\n// Validate ensures that h is configured properly.\nfunc (h *Handler) Validate() error {\n\tnDest, nDef := len(h.Destinations), len(h.Defaults)\n\tif nDef > 0 && nDef != nDest {\n\t\treturn fmt.Errorf(\"%d destinations != %d defaults\", nDest, nDef)\n\t}\n\n\tseen := make(map[string]int)\n\tfor i, m := range h.Mappings {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/map/map.go#L62-L98","documentation":"During Provision the map handler compiles each mapping's `input_regexp` with regexp.Compile. If any mapping's regular expression is invalid per Go's RE2 syntax, provisioning aborts with this error naming the mapping index and the underlying compile error.","triggerScenarios":"input_regexp values like \"[unclosed\", \"a{3,1}\" (quantifier range reversed), \"(?P<name\" (incomplete group), or PCRE-only constructs such as lookaheads \"foo(?=bar)\" that RE2 does not support.","commonSituations":"Porting regexes from PCRE/Perl/nginx (lookbehind, backreferences \\1, \\K) into Caddy; unescaped braces intended as literals while also using placeholders; shell/JSON escaping mangling backslashes so \\d becomes d.","solutions":["Test the pattern with Go's regexp.Compile (or grep -P will NOT suffice — use a RE2 tester).","Remove PCRE-only constructs: rewrite lookaheads as separate mappings or use alternation.","Escape literal braces: a\\{2\\} not a{2}.","Double-check backslash escaping through your config layer (JSON needs \\\\d for \\d)."],"exampleFix":"// before\nmap {path} {http.vars.x} {\n  regexp ^/foo(?=bar) foo\n}\n\n// after\nmap {path} {http.vars.x} {\n  regexp ^/foo(bar) foo\n}","handlingStrategy":"validation","validationCode":"import \"regexp\"\n\nfunc validRegexps(patterns []string) bool {\n\tfor _, p := range patterns {\n\t\tif _, err := regexp.Compile(p); err != nil {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Test patterns with Go's regexp (RE2), not PCRE testers.","Avoid lookarounds and backreferences.","Watch backslash escaping through JSON/shell layers."],"tags":["caddy","config","regex","map-handler","re2"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}