gorilla/mux · error
mux: unbalanced braces in
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.
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
AI-assisted analysis of gorilla/mux@db9d1d0073 (2026-08-04).
Data as JSON: /api/errors/2bb7ebf31337300c.
Report an issue: GitHub.
Appendix: 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)