{"record":{"id":"be4fc48f63483d72","repo":"caddyserver/caddy","slug":"mapping-d-has-both-input-and-input-regexp-fields","errorCode":null,"errorMessage":"mapping %d has both input and input_regexp fields specified, which is confusing","messagePattern":"mapping (.+?) has both input and input_regexp fields specified, which is confusing","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/map/map.go","lineNumber":101,"sourceCode":"\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 {\n\t\t// prevent confusing/ambiguous mappings\n\t\tif m.Input != \"\" && m.InputRegexp != \"\" {\n\t\t\treturn fmt.Errorf(\"mapping %d has both input and input_regexp fields specified, which is confusing\", i)\n\t\t}\n\n\t\t// prevent duplicate mappings\n\t\tinput := m.Input\n\t\tif m.InputRegexp != \"\" {\n\t\t\tinput = m.InputRegexp\n\t\t}\n\t\tif prev, ok := seen[input]; ok {\n\t\t\treturn fmt.Errorf(\"mapping %d has a duplicate input '%s' previously used with mapping %d\", i, input, prev)\n\t\t}\n\t\tseen[input] = i\n\n\t\t// ensure mappings have 1:1 output-to-destination correspondence\n\t\tnOut := len(m.Outputs)\n\t\tif nOut != nDest {\n\t\t\treturn fmt.Errorf(\"mapping %d has %d outputs but there are %d destinations defined\", i, nOut, nDest)\n\t\t}\n\t}","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/map/map.go#L83-L119","documentation":"Validate in the map handler rejects any mapping that sets both `input` (exact string) and `input_regexp`, because the two are mutually exclusive matching strategies and keeping both is ambiguous. The mapping index is reported.","triggerScenarios":"JSON map mapping objects containing {\"input\":\"foo\",\"input_regexp\":\"^foo\",\"outputs\":[...]}; Caddyfile regex mappings that also set an inline input.","commonSituations":"Editing a JSON config by hand and leaving the old field when switching to regexp; tooling that emits both fields defensively.","solutions":["Delete one of the two fields — keep `input` for exact matches or `input_regexp` for patterns.","Split into two mappings if you need both behaviors."],"exampleFix":"// before (JSON)\n{\"input\":\"foo\",\"input_regexp\":\"^foo$\",\"outputs\":[\"bar\"]}\n\n// after (JSON)\n{\"input_regexp\":\"^foo$\",\"outputs\":[\"bar\"]}","handlingStrategy":"validation","validationCode":"func exclusiveInput(m Mapping) bool {\n\treturn !(m.Input != \"\" && m.InputRegexp != \"\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When switching a mapping to regexp, delete the old input field.","Schema-validate JSON configs against the map handler shape."],"tags":["caddy","config","map-handler","validation","mutual-exclusion"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}