gorilla/mux · error · ErrNotFound
no matching route was found
Error message
no matching route was found
What it means
Sentinel error mux.ErrNotFound (mux.go:22). Assigned to RouteMatch.MatchErr when no registered route matches the request. Also used internally to short-circuit subrouter matching when a query matcher fails on a matching path (route.go:68-73). With no NotFoundHandler set, Router.ServeHTTP falls back to http.NotFoundHandler (mux.go:224-226).
Source
Thrown at mux.go:22
package mux
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"path"
"regexp"
)
var (
// ErrMethodMismatch is returned when the method in the request does not match
// the method defined against the route.
ErrMethodMismatch = errors.New("method is not allowed")
// ErrNotFound is returned when no route match is found.
ErrNotFound = errors.New("no matching route was found")
// RegexpCompileFunc aliases regexp.Compile and enables overriding it.
// Do not run this function from `init()` in importable packages.
// Changing this value is not safe for concurrent use.
RegexpCompileFunc = regexp.Compile
// ErrMetadataKeyNotFound is returned when the specified metadata key is not present in the map
ErrMetadataKeyNotFound = errors.New("key not found in metadata")
)
// NewRouter returns a new router instance.
func NewRouter() *Router {
return &Router{namedRoutes: make(map[string]*Route)}
}
// Router registers routes to be matched and dispatches a handler.
//
// It implements the http.Handler interface, so it can be registered to serve
// requests:
//View on GitHub (pinned to db9d1d0073)
Solutions
- Set router.NotFoundHandler to render the app's 404 JSON/page for clear diagnostics.
- Verify the request path against registered templates; mind trailing slash (consider router.StrictSlash(true)).
- If behind a proxy, confirm the path prefix is not being rewritten or stripped.
- Dump all routes via router.Walk and compare with the failing URL.
Example fix
// before
r.HandleFunc("/users/{id}", h)
// GET /user/42 (typo) -> 404
// after
r.HandleFunc("/users/{id}", h)
r.StrictSlash(true)
r.NotFoundHandler = http.HandlerFunc(notFoundJSON) Defensive patterns
Strategy: fallback
Validate before calling
// Pre-flight: does any route plausibly accept this path?
ok := false
_ = r.Walk(func(rt *mux.Route, _ *mux.Router, _ []*mux.Route) error {
if tpl, err := rt.GetPathTemplate(); err == nil && matchesTemplate(tpl, req.URL.Path) {
ok = true
}
return nil
}) Type guard
func isNotFound(m mux.RouteMatch) bool { return errors.Is(m.MatchErr, mux.ErrNotFound) } Try / catch
var match mux.RouteMatch
if !r.Match(req, &match) {
if errors.Is(match.MatchErr, mux.ErrNotFound) {
// render 404
}
} Prevention
- Always set a NotFoundHandler.
- Use StrictSlash consistently across the app.
- Dump routes via Walk in tests to catch missing registrations.
When it happens
Trigger: A request whose path/host/scheme/headers/queries match none of the registered routes; or a path matches but a .Queries(...) matcher does not, which sets ErrNotFound and breaks out of the matcher loop (route.go:68-73).
Common situations: Client URL typo; trailing-slash mismatch (StrictSlash off, client hits /users/ but route is /users); route registration skipped during refactor; reverse proxy stripping a path prefix; env-specific routes missing in staging.
Related errors
- method is not allowed
- key not found in metadata
- skip this router
- mux: duplicated route variable %q
- mux: number of parameters must be multiple of 2, got %v
AI-assisted analysis of gorilla/mux@db9d1d0073 (2026-08-04).
Data as JSON: /data/errors/6f88795ff34cb21d.json.
Report an issue: GitHub.