gorilla/mux · error · ErrMethodMismatch

method is not allowed

Error message

method is not allowed

What it means

Sentinel error mux.ErrMethodMismatch (mux.go:20). When a request's path matches a registered route but its HTTP method does not match any methodMatcher on that route, Route.Match sets RouteMatch.MatchErr = ErrMethodMismatch (route.go:58) and returns false. Router.Match (mux.go:164) and Router.ServeHTTP (mux.go:220) consult it to emit a 405 instead of a 404. It is a returned sentinel, not a panic.

Source

Thrown at mux.go:20

// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

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

View on GitHub (pinned to db9d1d0073)

Solutions

  1. Add the missing verb to the route's .Methods("GET", "PUT", ...) (and include OPTIONS for CORS preflight).
  2. Set router.MethodNotAllowedHandler to customize the 405 body.
  3. Treat errors.Is(match.MatchErr, mux.ErrMethodMismatch) as expected (not an error) in logging/metrics middleware.

Example fix

// before
r.HandleFunc("/users/{id}", h).Methods("GET")
// client does PUT /users/42 -> 405

// after
r.HandleFunc("/users/{id}", h).Methods("GET", "PUT")
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the method is registered before relying on a match
methods, err := route.GetMethods()
if err == nil && !contains(methods, req.Method) {
    write405(w, req)
    return
}

Type guard

// Narrow the match failure to a method mismatch
func isMethodMismatch(m mux.RouteMatch) bool {
    return errors.Is(m.MatchErr, mux.ErrMethodMismatch)
}

Try / catch

var match mux.RouteMatch
if r.Match(req, &match) {
    match.Handler.ServeHTTP(w, req)
    return
}
if errors.Is(match.MatchErr, mux.ErrMethodMismatch) {
    // 405 path
}

Prevention

When it happens

Trigger: Client sends PUT /users/42 when only r.HandleFunc("/users/{id}", h).Methods("GET") is registered. The path matcher succeeds but the methodMatcher fails, so matchErr becomes ErrMethodMismatch; if no other route matches it propagates out in RouteMatch.MatchErr.

Common situations: Forgotten verb in .Methods(...); CORS preflight OPTIONS hitting a route that does not list OPTIONS; REST verb typo; load-balancer HEAD/health probes against GET-only routes; reverse proxy rewriting the method.

Related errors


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