{"id":"5407e15e09d79eb6","repo":"gorilla/mux","slug":"mux-duplicated-route-variable-q","errorCode":null,"errorMessage":"mux: duplicated route variable %q","messagePattern":"mux: duplicated route variable %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mux.go","lineNumber":554,"sourceCode":"\t}\n\n\treturn np\n}\n\n// replaceURLPath prints an url.URL with a different path.\nfunc replaceURLPath(u *url.URL, p string) string {\n\t// Operate on a copy of the request url.\n\tu2 := *u\n\tu2.Path = p\n\treturn u2.String()\n}\n\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","sourceCodeStart":536,"sourceCodeEnd":572,"githubUrl":"https://github.com/gorilla/mux/blob/db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265/mux.go#L536-L572","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nr.Host(\"{id}.example.com\").Path(\"/items/{id}\")\n// -> mux: duplicated route variable \"id\"\n\n// after\nr.Host(\"{tenantId}.example.com\").Path(\"/items/{id}\")","handlingStrategy":"validation","validationCode":"// Reject templates that reuse a variable name across host/path/query\nfunc distinctVars(hostTpl, pathTpl string) error {\n    hv, pv := extractVars(hostTpl), extractVars(pathTpl)\n    for v := range hv {\n        if _, ok := pv[v]; ok {\n            return fmt.Errorf(\"var %q reused across host and path\", v)\n        }\n    }\n    return nil\n}","typeGuard":"// After building, confirm the route is usable\nfunc routeOK(r *mux.Route) bool { return r != nil && r.GetError() == nil }","tryCatchPattern":"rt := r.Host(h).Path(p)\nif err := rt.GetError(); err != nil {\n    log.Fatalf(\"route build failed: %v\", err)\n}","preventionTips":["Use distinct, role-prefixed variable names.","Call GetError() in unit tests for every route.","Lint route templates in CI."],"tags":["routing","config","regexp","build-time","variables"],"analyzedSha":"db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265","analyzedAt":"2026-08-04T21:35:47.097Z","schemaVersion":2}