{"id":"f56f56fc48a2c976","repo":"gorilla/mux","slug":"mux-number-of-parameters-must-be-multiple-of-2-g","errorCode":null,"errorMessage":"mux: number of parameters must be multiple of 2, got %v","messagePattern":"mux: number of parameters must be multiple of 2, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mux.go","lineNumber":566,"sourceCode":"\n// uniqueVars returns an error if two slices contain duplicated strings.\nfunc uniqueVars(s1, s2 []string) error {\n\tfor _, v1 := range s1 {\n\t\tfor _, v2 := range s2 {\n\t\t\tif v1 == v2 {\n\t\t\t\treturn fmt.Errorf(\"mux: duplicated route variable %q\", v2)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// checkPairs returns the count of strings passed in, and an error if\n// the count is not an even number.\nfunc checkPairs(pairs ...string) (int, error) {\n\tlength := len(pairs)\n\tif length%2 != 0 {\n\t\treturn length, fmt.Errorf(\n\t\t\t\"mux: number of parameters must be multiple of 2, got %v\", pairs)\n\t}\n\treturn length, nil\n}\n\n// mapFromPairsToString converts variadic string parameters to a\n// string to string map.\nfunc mapFromPairsToString(pairs ...string) (map[string]string, error) {\n\tlength, err := checkPairs(pairs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tm := make(map[string]string, length/2)\n\tfor i := 0; i < length; i += 2 {\n\t\tm[pairs[i]] = pairs[i+1]\n\t}\n\treturn m, nil\n}","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/gorilla/mux/blob/db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265/mux.go#L548-L584","documentation":"Returned by checkPairs (mux.go:563-569) when the variadic string pairs passed to a key/value matcher are odd (a key missing its value). It propagates through mapFromPairsToString / mapFromPairsToRegex into Headers, HeadersRegexp, and prepareVars (used by URL/URLHost/URLPath), and is stored on r.err.","triggerScenarios":"r.Headers(\"Content-Type\", \"application/json\", \"X-Trace\") (3 args), or r.Get(\"x\").URL(\"id\", \"42\", \"extra\") (3 args to URL which routes through prepareVars).","commonSituations":"Dropping a value while editing a Headers call; passing a slice unpacked with pairs... whose length is odd; misreading the key,value,key,value contract.","solutions":["Ensure Headers/HeadersRegexp/URL-style calls always pass an even number of args.","Build the pairs slice explicitly and assert len%2 == 0 before calling.","Check route.GetError() right after construction to surface the failure."],"exampleFix":"// before\nr.Headers(\"Content-Type\", \"application/json\", \"X-Trace\")\n// odd number of args -> r.err set\n\n// after\nr.Headers(\"Content-Type\", \"application/json\", \"X-Trace\", \"\")","handlingStrategy":"validation","validationCode":"func evenPairs(pairs ...string) error {\n    if len(pairs)%2 != 0 {\n        return fmt.Errorf(\"odd pair count: %d\", len(pairs))\n    }\n    return nil\n}","typeGuard":"func validHeadersCall(pairs ...string) bool { return len(pairs)%2 == 0 }","tryCatchPattern":"rt := r.Headers(pairs...)\nif err := rt.GetError(); err != nil {\n    return err\n}","preventionTips":["Keep header/query/URL pairs as named struct fields, not loose slices.","Static-check arg counts in wrapper helpers.","Unit-test route construction."],"tags":["routing","config","arguments","build-time"],"analyzedSha":"db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265","analyzedAt":"2026-08-04T21:35:47.097Z","schemaVersion":2}