gorilla/mux · error
mux: duplicated route variable %q
Error message
mux: duplicated route variable %q
What it means
Returned by uniqueVars (mux.go:550-555) when two variable-bearing matchers on the same route reuse a variable name. It is invoked during route construction from addRegexpMatcher (route.go:267, 273, 280) and stored on r.err, which disables the route. The same name cannot map to two capture slots.
Source
Thrown at mux.go:554
}
return np
}
// replaceURLPath prints an url.URL with a different path.
func replaceURLPath(u *url.URL, p string) string {
// Operate on a copy of the request url.
u2 := *u
u2.Path = p
return u2.String()
}
// 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 aView on GitHub (pinned to db9d1d0073)
Solutions
- Give each capture a distinct, role-prefixed name (e.g. {tenantId} for host vs {id} for path).
- Capture the variable once on a single matcher instead of repeating it.
- Call route.GetError() right after construction to surface this at startup.
Example fix
// before
r.Host("{id}.example.com").Path("/items/{id}")
// -> mux: duplicated route variable "id"
// after
r.Host("{tenantId}.example.com").Path("/items/{id}") Defensive patterns
Strategy: validation
Validate before calling
// Reject templates that reuse a variable name across host/path/query
func distinctVars(hostTpl, pathTpl string) error {
hv, pv := extractVars(hostTpl), extractVars(pathTpl)
for v := range hv {
if _, ok := pv[v]; ok {
return fmt.Errorf("var %q reused across host and path", v)
}
}
return nil
} Type guard
// After building, confirm the route is usable
func routeOK(r *mux.Route) bool { return r != nil && r.GetError() == nil } Try / catch
rt := r.Host(h).Path(p)
if err := rt.GetError(); err != nil {
log.Fatalf("route build failed: %v", err)
} Prevention
- Use distinct, role-prefixed variable names.
- Call GetError() in unit tests for every route.
- Lint route templates in CI.
When it happens
Trigger: r.Host("{id}.example.com").Path("/items/{id}") (host and path both declare id), or r.Path("/u/{id}").Queries("ref", "{id}") (path and query both declare id).
Common situations: Copy-pasting variable names across host/path/query; renaming a var in one place but not the other; a subrouter inheriting a host var and redeclaring it on a child path.
Related errors
- mux: missing name or pattern in %q
- mux: error compiling regex for %q: %w
- route %s contains capture groups in its regexp. Only non-cap
- mux: number of parameters must be multiple of 2, got %v
- mux: route already has name %q, can't set %q
AI-assisted analysis of gorilla/mux@db9d1d0073 (2026-08-04).
Data as JSON: /data/errors/5407e15e09d79eb6.json.
Report an issue: GitHub.