{"id":"2bb7ebf31337300c","repo":"gorilla/mux","slug":"mux-unbalanced-braces-in-q","errorCode":null,"errorMessage":"mux: unbalanced braces in %q","messagePattern":"mux: unbalanced braces in %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"regexp.go","lineNumber":312,"sourceCode":"\treturn r.regexp.MatchString(r.getURLQuery(req))\n}\n\n// braceIndices returns the first level curly brace indices from a string.\n// It returns an error in case of unbalanced braces.\nfunc braceIndices(s string) ([]int, error) {\n\tvar level, idx int\n\tvar idxs []int\n\tfor i := 0; i < len(s); i++ {\n\t\tswitch s[i] {\n\t\tcase '{':\n\t\t\tif level++; level == 1 {\n\t\t\t\tidx = i\n\t\t\t}\n\t\tcase '}':\n\t\t\tif level--; level == 0 {\n\t\t\t\tidxs = append(idxs, idx, i+1)\n\t\t\t} else if level < 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"mux: unbalanced braces in %q\", s)\n\t\t\t}\n\t\t}\n\t}\n\tif level != 0 {\n\t\treturn nil, fmt.Errorf(\"mux: unbalanced braces in %q\", s)\n\t}\n\treturn idxs, nil\n}\n\n// varGroupName builds a capturing group name for the indexed variable.\nfunc varGroupName(idx int) string {\n\treturn \"v\" + strconv.Itoa(idx)\n}\n\n// ----------------------------------------------------------------------------\n// routeRegexpGroup\n// ----------------------------------------------------------------------------\n","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/gorilla/mux/blob/db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265/regexp.go#L294-L330","documentation":"Returned by braceIndices() (regexp.go:312) when scanning a route template and a '}' is encountered while the brace nesting level is already 0 — i.e. a closing brace with no matching opening brace earlier in the string. newRouteRegexp propagates this when registering the route, so it surfaces at Router setup time, not request time.","triggerScenarios":"r.NewRoute().Path(\"/foo}bar\"), .Host(\"api}.example.com\"), or .Queries(\"k\", \"{v}\")-style templates containing a literal '}' that isn't part of a {...} variable. Also triggered by regexp quantifier braces such as /items/{id:[0-9]{2,4}} where the inner {2,4} is misread as a variable delimiter.","commonSituations":"Copy-pasting a URL that legitimately contains a brace; attempting an inline bounded quantifier inside a variable pattern without realising mux parses top-level braces; truncating or hand-editing a template and dropping the opening '{'.","solutions":["Locate the stray '}' reported by the offending template (the %q) and remove it or balance it with a matching '{'.","If you need a regexp bounded quantifier like {2,4}, keep it entirely inside a variable's pattern segment, e.g. {id:[0-9]{2,4}}, so the outer brace pair still balances.","For a genuinely literal brace in the path, escape it within the variable pattern (e.g. {lit:\\}\\{foo}) rather than leaving it bare.","Register routes in a test (router.Walk / a smoke Handler request) so the failure is caught at startup, not in production boot."],"exampleFix":"// before: stray closing brace\nr.NewRoute().Path(\"/foo}bar\")\n// -> mux: unbalanced braces in \"/foo}bar\"\n\n// after\nr.NewRoute().Path(\"/foobar\")\n\n// if you wanted a bounded digit quantifier, keep braces paired inside the var pattern\nr.NewRoute().Path(\"/items/{id:[0-9]{2,4}}\")","handlingStrategy":"validation","validationCode":"// Reject stray '}' (closing brace with no matching '{') before registering a route.\nfunc balancedBraces(tpl string) error {\n    level := 0\n    for i := 0; i < len(tpl); i++ {\n        switch tpl[i] {\n        case '{':\n            level++\n        case '}':\n            level--\n            if level < 0 {\n                return fmt.Errorf(\"stray '}' at offset %d in %q\", i, tpl)\n            }\n        }\n    }\n    if level != 0 {\n        return fmt.Errorf(\"unbalanced '{' in %q\", tpl)\n    }\n    return nil\n}\n\nif err := balancedBraces(tpl); err != nil { return err }\nr.NewRoute().Path(tpl)","typeGuard":null,"tryCatchPattern":"// Registration-time: build the router in a function that returns an error.\nrouter, err := buildRouter()\nif err != nil {\n    // err.Error() is: mux: unbalanced braces in %q\n    log.Fatalf(\"router setup failed: %v\", err)\n}","preventionTips":["Construct the router inside a function that returns (*mux.Router, error) so newRouteRegexp's error propagates instead of panicking at boot.","Keep regexp quantifier braces like {2,4} strictly inside a variable's :pattern body so the top-level pair still balances.","Add a unit test that walks the router (router.Walk) and issues one sample request per route to catch template errors in CI.","Lint route templates during code review — any literal { or } outside a {...} variable is suspect."],"tags":["routing","configuration","template","startup","gorilla-mux"],"analyzedSha":"db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265","analyzedAt":"2026-08-04T21:35:47.097Z","schemaVersion":2}