gorilla/mux · error
mux: unbalanced braces in %q
Error message
mux: unbalanced braces in %q
What it means
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.
Source
Thrown at regexp.go:312
return r.regexp.MatchString(r.getURLQuery(req))
}
// braceIndices returns the first level curly brace indices from a string.
// It returns an error in case of unbalanced braces.
func braceIndices(s string) ([]int, error) {
var level, idx int
var idxs []int
for i := 0; i < len(s); i++ {
switch s[i] {
case '{':
if level++; level == 1 {
idx = i
}
case '}':
if level--; level == 0 {
idxs = append(idxs, idx, i+1)
} else if level < 0 {
return nil, fmt.Errorf("mux: unbalanced braces in %q", s)
}
}
}
if level != 0 {
return nil, fmt.Errorf("mux: unbalanced braces in %q", s)
}
return idxs, nil
}
// varGroupName builds a capturing group name for the indexed variable.
func varGroupName(idx int) string {
return "v" + strconv.Itoa(idx)
}
// ----------------------------------------------------------------------------
// routeRegexpGroup
// ----------------------------------------------------------------------------
View on GitHub (pinned to db9d1d0073)
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.
Example fix
// before: stray closing brace
r.NewRoute().Path("/foo}bar")
// -> mux: unbalanced braces in "/foo}bar"
// after
r.NewRoute().Path("/foobar")
// if you wanted a bounded digit quantifier, keep braces paired inside the var pattern
r.NewRoute().Path("/items/{id:[0-9]{2,4}}") Defensive patterns
Strategy: validation
Validate before calling
// Reject stray '}' (closing brace with no matching '{') before registering a route.
func balancedBraces(tpl string) error {
level := 0
for i := 0; i < len(tpl); i++ {
switch tpl[i] {
case '{':
level++
case '}':
level--
if level < 0 {
return fmt.Errorf("stray '}' at offset %d in %q", i, tpl)
}
}
}
if level != 0 {
return fmt.Errorf("unbalanced '{' in %q", tpl)
}
return nil
}
if err := balancedBraces(tpl); err != nil { return err }
r.NewRoute().Path(tpl) Try / catch
// Registration-time: build the router in a function that returns an error.
router, err := buildRouter()
if err != nil {
// err.Error() is: mux: unbalanced braces in %q
log.Fatalf("router setup failed: %v", err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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 '{'.
Related errors
- mux: missing route variable %q
- mux: variable %q doesn't match, expected %q
- method is not allowed
- no matching route was found
- key not found in metadata
AI-assisted analysis of gorilla/mux@db9d1d0073 (2026-08-04).
Data as JSON: /data/errors/2bb7ebf31337300c.json.
Report an issue: GitHub.