gorilla/mux · error
mux: number of parameters must be multiple of 2, got %v
Error message
mux: number of parameters must be multiple of 2, got %v
What it means
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.
Source
Thrown at mux.go:566
// uniqueVars returns an error if two slices contain duplicated strings.
func uniqueVars(s1, s2 []string) error {
for _, v1 := range s1 {
for _, v2 := range s2 {
if v1 == v2 {
return fmt.Errorf("mux: duplicated route variable %q", v2)
}
}
}
return nil
}
// checkPairs returns the count of strings passed in, and an error if
// the count is not an even number.
func checkPairs(pairs ...string) (int, error) {
length := len(pairs)
if length%2 != 0 {
return length, fmt.Errorf(
"mux: number of parameters must be multiple of 2, got %v", pairs)
}
return length, nil
}
// mapFromPairsToString converts variadic string parameters to a
// string to string map.
func mapFromPairsToString(pairs ...string) (map[string]string, error) {
length, err := checkPairs(pairs...)
if err != nil {
return nil, err
}
m := make(map[string]string, length/2)
for i := 0; i < length; i += 2 {
m[pairs[i]] = pairs[i+1]
}
return m, nil
}View on GitHub (pinned to db9d1d0073)
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.
Example fix
// before
r.Headers("Content-Type", "application/json", "X-Trace")
// odd number of args -> r.err set
// after
r.Headers("Content-Type", "application/json", "X-Trace", "") Defensive patterns
Strategy: validation
Validate before calling
func evenPairs(pairs ...string) error {
if len(pairs)%2 != 0 {
return fmt.Errorf("odd pair count: %d", len(pairs))
}
return nil
} Type guard
func validHeadersCall(pairs ...string) bool { return len(pairs)%2 == 0 } Try / catch
rt := r.Headers(pairs...)
if err := rt.GetError(); err != nil {
return err
} Prevention
- Keep header/query/URL pairs as named struct fields, not loose slices.
- Static-check arg counts in wrapper helpers.
- Unit-test route construction.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- mux: duplicated route variable %q
- mux: route already has name %q, can't set %q
- mux: path must start with a slash, got %q
- mux: number of parameters must be multiple of 2, got %v
- mux: missing name or pattern in %q
AI-assisted analysis of gorilla/mux@db9d1d0073 (2026-08-04).
Data as JSON: /data/errors/f56f56fc48a2c976.json.
Report an issue: GitHub.