{"record":{"id":"e0b31f8613ae4ee1","repo":"caddyserver/caddy","slug":"d-destinations-d-defaults","errorCode":null,"errorMessage":"%d destinations != %d defaults","messagePattern":"(.+?) destinations != (.+?) defaults","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/map/map.go","lineNumber":94,"sourceCode":"\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 {\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","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/map/map.go#L76-L112","documentation":"The map handler's Validate enforces that if `defaults` is non-empty its length equals the number of `destinations`, since each destination needs exactly one default value. A mismatch aborts config validation with both counts in the message.","triggerScenarios":"map with 2 destinations and 3 defaults (or 1), e.g. destinations [{http.vars.a} {http.vars.b}] with defaults [\"x\"].","commonSituations":"Adding a destination later and forgetting the defaults; removing a destination while keeping old defaults; assuming defaults apply positionally to a single combined output.","solutions":["Make len(defaults) == len(destinations): one default per destination, in order.","If you truly want no default, omit the defaults array entirely.","Re-count both arrays after editing the map block."],"exampleFix":"// before (Caddyfile)\nmap {http.request.host} {http.vars.a} {http.vars.b} {\n  default one\n}\n\n// after\nmap {http.request.host} {http.vars.a} {http.vars.b} {\n  default one two\n}","handlingStrategy":"validation","validationCode":"func balancedMapConfig(dests, defaults []string) bool {\n\tif len(defaults) == 0 {\n\t\treturn true\n\t}\n\treturn len(defaults) == len(dests)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Update defaults whenever destinations change.","Omit defaults entirely if none are needed.","Treat map arity as a schema: destinations count drives every row."],"tags":["caddy","config","map-handler","validation","arity"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}