gorilla/mux · error

mux: variable %q doesn't match, expected %q

Error message

mux: variable %q doesn't match, expected %q

What it means

Returned by routeRegexp.url() (regexp.go:231) when reverse URL building succeeds in formatting the string but the full regexp then fails to MatchString it. mux re-checks each variable's own pattern (varsR) and reports the first value that violates its constraint, printing both the offending value and the expected regexp.

Source

Thrown at regexp.go:231

	urlValues := make([]interface{}, len(r.varsN))
	for k, v := range r.varsN {
		value, ok := values[v]
		if !ok {
			return "", fmt.Errorf("mux: missing route variable %q", v)
		}
		if r.regexpType == regexpTypeQuery {
			value = url.QueryEscape(value)
		}
		urlValues[k] = value
	}
	rv := fmt.Sprintf(r.reverse, urlValues...)
	if !r.regexp.MatchString(rv) {
		// The URL is checked against the full regexp, instead of checking
		// individual variables. This is faster but to provide a good error
		// message, we check individual regexps if the URL doesn't match.
		for k, v := range r.varsN {
			if !r.varsR[k].MatchString(values[v]) {
				return "", fmt.Errorf(
					"mux: variable %q doesn't match, expected %q", values[v],
					r.varsR[k].String())
			}
		}
	}
	return rv, nil
}

// getURLQuery returns a single query parameter from a request URL.
// For a URL with foo=bar&baz=ding, we return only the relevant key
// value pair for the routeRegexp.
func (r *routeRegexp) getURLQuery(req *http.Request) string {
	if r.regexpType != regexpTypeQuery {
		return ""
	}
	templateKey := strings.SplitN(r.template, "=", 2)[0]
	val, ok := findFirstQueryKey(req.URL.RawQuery, templateKey)
	if ok {

View on GitHub (pinned to db9d1d0073)

Solutions

  1. Inspect the expected regexp in the error and validate the value with regexp.MustCompile(thatPattern).MatchString(value) before calling URL().
  2. If the value legitimately can be that shape, widen the route's inline pattern (e.g. {id:[0-9a-zA-Z_-]+}).
  3. For user-supplied IDs, reject early with HTTP 400 / a typed error rather than letting URL() fail.
  4. Normalize the value first (trim, lowercase, url.PathEscape only where appropriate) so it matches the declared charset.

Example fix

// before
url, err := r.Get("article").URL("id", userInput)
// userInput="abc" -> mux: variable "abc" doesn't match, expected "[0-9]+"

// after: validate against the same constraint before building
var idRe = regexp.MustCompile(`^[0-9]+$`)
if !idRe.MatchString(userInput) {
    return errors.New("invalid id")
}
url, err := r.Get("article").URL("id", userInput)
Defensive patterns

Strategy: validation

Validate before calling

// Reuse the route's own constraint by compiling the pattern you declared.
// e.g. Path("/articles/{id:[0-9]+}") -> validate with the same regexp.
var idRe = regexp.MustCompile(`^[0-9]+$`)

func validID(s string) bool { return idRe.MatchString(s) }

// call before URL()
if !validID(id) {
    return fmt.Errorf("id %q violates [0-9]+", id)
}
u, err := r.Get("article").URL("id", id)

Try / catch

u, err := r.Get("article").URL("id", id)
if err != nil {
    // Surface the offending value and expected pattern to the caller,
    // or map to HTTP 400 if the value came from a client.
    var val, want string
    if n, _ := fmt.Sscanf(err.Error(),
        "mux: variable %q doesn't match, expected %q", &val, &want); n == 2 {
        return fmt.Errorf("invalid value %q: must match %s", val, want)
    }
    return err
}

Prevention

When it happens

Trigger: Route declares a constraint and the caller supplies a non-conforming value, e.g. Path("/articles/{id:[0-9]+}") plus URL("id", "abc"), or Host("{sub:[a-z]+}.example.com") plus URL("sub", "News42"), or a query {q:[a-z]+} with uppercase/symbols.

Common situations: Raw user input is forwarded into URL() without sanitization; a route's inline regexp was tightened (e.g. [0-9]+ added) but producers still emit old formats; locale/unicode characters slip into an ASCII-only pattern; values containing '/' hit the default [^/]+ reversal in surprising ways.

Related errors


AI-assisted analysis of gorilla/mux@db9d1d0073 (2026-08-04). Data as JSON: /data/errors/6c91aaf0f03f5be3.json. Report an issue: GitHub.