gorilla/mux · error

mux: missing route variable %q

Error message

mux: missing route variable %q

What it means

Returned by routeRegexp.url() (regexp.go:217) during reverse URL building via Route.URL/URLPath/URLHost when a named placeholder declared in the route template has no entry in the supplied pairs. gorilla/mux treats every {...} variable as required, so omitting any one aborts URL construction and surfaces the missing variable name in the message.

Source

Thrown at regexp.go:217

	}

	if r.regexpType == regexpTypeQuery {
		return r.matchQueryString(req)
	}
	path := req.URL.Path
	if r.options.useEncodedPath {
		path = req.URL.EscapedPath()
	}
	return r.regexp.MatchString(path)
}

// url builds a URL part using the given values.
func (r *routeRegexp) url(values map[string]string) (string, error) {
	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())
			}
		}

View on GitHub (pinned to db9d1d0073)

Solutions

  1. Read the variable name in the error message (the %q) and add the corresponding "name", "value" pair to the URL/URLPath/URLHost call.
  2. Cross-check against r.GetPathTemplate() (or GetHostTemplate) to enumerate every required variable before constructing the URL.
  3. Wrap URL() construction in a helper that takes a map[string]string and asserts it covers GetPathTemplate()'s variables, failing loudly at startup.
  4. If the variable is genuinely optional, split the route into two routes (one with, one without the segment) instead of trying to omit it.

Example fix

// before: route is /articles/{category}/{id:[0-9]+}
url, err := r.Get("article").URL("category", "tech")
// err: mux: missing route variable "id"

// after
url, err := r.Get("article").URL("category", "tech", "id", "42")
Defensive patterns

Strategy: validation

Validate before calling

// Validate before calling Route.URL / URLPath / URLHost
tpl, err := r.Get("article").GetPathTemplate()
if err != nil { return err }

required := routeVarNames(tpl) // parses {name} and {name:pat} out of tpl
provided := map[string]string{"category": cat, "id": id} // your pairs
for _, name := range required {
    if _, ok := provided[name]; !ok {
        return fmt.Errorf("missing route variable %q", name)
    }
}
return nil

// helper
func routeVarNames(tpl string) []string {
    var out []string
    for i := 0; i < len(tpl); i++ {
        if tpl[i] != '{' { continue }
        j := strings.IndexByte(tpl[i:], '}')
        if j < 0 { break }
        body := tpl[i+1 : i+j]
        if c := strings.IndexByte(body, ':'); c >= 0 { body = body[:c] }
        out = append(out, body)
        i += j
    }
    return out
}

Try / catch

// Go: check the returned error, don't ignore it.
u, err := r.Get("article").URL("category", cat, "id", id)
if err != nil {
    // err.Error() is exactly: mux: missing route variable %q
    var name string
    if _, gerr := fmt.Sscanf(err.Error(), "mux: missing route variable %q", &name); gerr == nil {
        return fmt.Errorf("cannot build URL: required variable %s not supplied", name)
    }
    return err
}
return u

Prevention

When it happens

Trigger: Calling r.Get("article").URL("category", "tech") for a route registered as Path("/articles/{category}/{id:[0-9]+}") — id is missing. Same for URLPath/URLHost when the host/path template declares more variables than the caller passes.

Common situations: A new {var} was added to a route template but an existing URL() call site wasn't updated; a variable was renamed; key/value pairs were passed in the wrong even/odd order so a value landed where a key was expected; refactor moved URL building into a helper that dropped a pair.

Related errors


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