{"id":"0966225982f14d6e","repo":"gorilla/mux","slug":"skip-this-router","errorCode":null,"errorMessage":"skip this router","messagePattern":"skip this router","errorType":"error_code","errorClass":"SkipRouter","httpStatus":null,"severity":"info","filePath":"mux.go","lineNumber":403,"sourceCode":"\treturn r.NewRoute().Schemes(schemes...)\n}\n\n// BuildVarsFunc registers a new route with a custom function for modifying\n// route variables before building a URL.\nfunc (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route {\n\treturn r.NewRoute().BuildVarsFunc(f)\n}\n\n// Walk walks the router and all its sub-routers, calling walkFn for each route\n// in the tree. The routes are walked in the order they were added. Sub-routers\n// are explored depth-first.\nfunc (r *Router) Walk(walkFn WalkFunc) error {\n\treturn r.walk(walkFn, []*Route{})\n}\n\n// SkipRouter is used as a return value from WalkFuncs to indicate that the\n// router that walk is about to descend down to should be skipped.\nvar SkipRouter = errors.New(\"skip this router\")\n\n// WalkFunc is the type of the function called for each route visited by Walk.\n// At every invocation, it is given the current route, and the current router,\n// and a list of ancestor routes that lead to the current route.\ntype WalkFunc func(route *Route, router *Router, ancestors []*Route) error\n\nfunc (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {\n\tfor _, t := range r.routes {\n\t\terr := walkFn(t, r, ancestors)\n\t\tif err == SkipRouter {\n\t\t\tcontinue\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, sr := range t.matchers {\n\t\t\tif h, ok := sr.(*Router); ok {\n\t\t\t\tancestors = append(ancestors, t)","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/gorilla/mux/blob/db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265/mux.go#L385-L421","documentation":"Sentinel mux.SkipRouter (mux.go:403) is a control-flow signal, not a failure. A WalkFunc returns SkipRouter to tell Router.walk (mux.go:413-415) to skip descending into the current route's subrouter. The library compares with == and continues; any other returned error aborts the walk.","triggerScenarios":"Inside a WalkFunc you return mux.SkipRouter to prune a subrouter from the traversal, e.g. skipping an admin subrouter while generating docs for the public site.","commonSituations":"Generating route docs/diagnostics and pruning internal subrouters; OpenAPI generation skipping auth subrouters; accidentally wrapping SkipRouter so the library's == check no longer recognizes it.","solutions":["Return mux.SkipRouter directly (do not wrap it) from the WalkFunc to prune one subrouter.","Remember the library compares with ==, so never errors.Wrap/errors.Join it.","Return any non-SkipRouter error to abort the walk entirely."],"exampleFix":"// before\nr.Walk(func(rt *mux.Route, _ *mux.Router, _ []*mux.Route) error {\n    return errors.New(\"skip\") // aborts the whole walk!\n})\n\n// after\nr.Walk(func(rt *mux.Route, _ *mux.Router, _ []*mux.Route) error {\n    if isAdmin(rt) { return mux.SkipRouter }\n    return nil\n})","handlingStrategy":"validation","validationCode":"// In your WalkFunc, only return SkipRouter intentionally\nfunc walk(rt *mux.Route, _ *mux.Router, _ []*mux.Route) error {\n    if shouldPrune(rt) { return mux.SkipRouter }\n    return nil\n}","typeGuard":"func isSkipRouter(err error) bool { return errors.Is(err, mux.SkipRouter) }","tryCatchPattern":"err := r.Walk(fn)\nif err != nil && !errors.Is(err, mux.SkipRouter) {\n    return err\n}","preventionTips":["Never wrap SkipRouter; the library compares with ==.","Return nil to continue, SkipRouter to prune, anything else to abort.","Document which WalkFuncs prune subrouters."],"tags":["routing","walk","control-flow","sentinel"],"analyzedSha":"db9d1d0073d27a0a2d9a8c1bc52aa0af4374d265","analyzedAt":"2026-08-04T21:35:47.097Z","schemaVersion":2}