{"id":"bd7345029e296408","repo":"gorilla/mux","slug":"method-is-not-allowed","errorCode":null,"errorMessage":"method is not allowed","messagePattern":"method is not allowed","errorType":"error_code","errorClass":"ErrMethodMismatch","httpStatus":null,"severity":"error","filePath":"mux.go","lineNumber":20,"sourceCode":"// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage mux\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"regexp\"\n)\n\nvar (\n\t// ErrMethodMismatch is returned when the method in the request does not match\n\t// the method defined against the route.\n\tErrMethodMismatch = errors.New(\"method is not allowed\")\n\t// ErrNotFound is returned when no route match is found.\n\tErrNotFound = errors.New(\"no matching route was found\")\n\t// RegexpCompileFunc aliases regexp.Compile and enables overriding it.\n\t// Do not run this function from `init()` in importable packages.\n\t// Changing this value is not safe for concurrent use.\n\tRegexpCompileFunc = regexp.Compile\n\t// ErrMetadataKeyNotFound is returned when the specified metadata key is not present in the map\n\tErrMetadataKeyNotFound = errors.New(\"key not found in metadata\")\n)\n\n// NewRouter returns a new router instance.\nfunc NewRouter() *Router {\n\treturn &Router{namedRoutes: make(map[string]*Route)}\n}\n\n// Router registers routes to be matched and dispatches a handler.\n//\n// It implements the http.Handler interface, so it can be registered to serve","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/gorilla/mux/blob/db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265/mux.go#L2-L38","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add the missing verb to the route's .Methods(\"GET\", \"PUT\", ...) (and include OPTIONS for CORS preflight).","Set router.MethodNotAllowedHandler to customize the 405 body.","Treat errors.Is(match.MatchErr, mux.ErrMethodMismatch) as expected (not an error) in logging/metrics middleware."],"exampleFix":"// before\nr.HandleFunc(\"/users/{id}\", h).Methods(\"GET\")\n// client does PUT /users/42 -> 405\n\n// after\nr.HandleFunc(\"/users/{id}\", h).Methods(\"GET\", \"PUT\")","handlingStrategy":"try-catch","validationCode":"// Confirm the method is registered before relying on a match\nmethods, err := route.GetMethods()\nif err == nil && !contains(methods, req.Method) {\n    write405(w, req)\n    return\n}","typeGuard":"// Narrow the match failure to a method mismatch\nfunc isMethodMismatch(m mux.RouteMatch) bool {\n    return errors.Is(m.MatchErr, mux.ErrMethodMismatch)\n}","tryCatchPattern":"var match mux.RouteMatch\nif r.Match(req, &match) {\n    match.Handler.ServeHTTP(w, req)\n    return\n}\nif errors.Is(match.MatchErr, mux.ErrMethodMismatch) {\n    // 405 path\n}","preventionTips":["Register a MethodNotAllowedHandler so 405s are visible and consistent.","List every supported verb (including OPTIONS for CORS) on each route.","Log match.MatchErr in dev to distinguish 404 from 405."],"tags":["http","routing","method-mismatch","runtime","sentinel"],"analyzedSha":"db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265","analyzedAt":"2026-08-04T21:35:47.097Z","schemaVersion":2}