{"id":"41aaca798045d273","repo":"labstack/echo","slug":"adding-route-without-handler-function","errorCode":null,"errorMessage":"adding route without handler function","messagePattern":"adding route without handler function","errorType":"validation","errorClass":"AddRouteError","httpStatus":null,"severity":"error","filePath":"router.go","lineNumber":518,"sourceCode":"\treturn &AddRouteError{\n\t\tMethod: route.Method,\n\t\tPath:   route.Path,\n\t\tErr:    err,\n\t}\n}\n\n// Add registers a new route for method and path with matching handler.\nfunc (r *DefaultRouter) Add(route Route) (RouteInfo, error) {\n\tallowOverwritingRoute := r.allowOverwritingRoute || route.allowOverwrite\n\n\tif route.Handler == nil {\n\t\tswitch route.Method {\n\t\tcase RouteNotFound:\n\t\t\troute.Handler = r.notFoundHandler\n\t\tcase http.MethodOptions:\n\t\t\troute.Handler = r.optionsMethodHandler\n\t\tdefault:\n\t\t\treturn RouteInfo{}, newAddRouteError(route, errors.New(\"adding route without handler function\"))\n\t\t}\n\t}\n\n\tmethod := route.Method\n\tpath := normalizePathSlash(route.Path)\n\n\th := applyMiddleware(route.Handler, route.Middlewares...)\n\tif !allowOverwritingRoute {\n\t\tfor _, rr := range r.routes {\n\t\t\tif route.Method == rr.Method && route.Path == rr.Path {\n\t\t\t\treturn RouteInfo{}, newAddRouteError(route, errors.New(\"adding duplicate route (same method+path) is not allowed\"))\n\t\t\t}\n\t\t}\n\t}\n\tvar headH HandlerFunc\n\tif r.autoHandleHEAD && method == http.MethodGet {\n\t\theadH = wrapHeadHandler(h)\n\t}","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/router.go#L500-L536","documentation":"Returned by DefaultRouter.Add (router.go:517-519) when the Route has a nil Handler and Method is neither RouteNotFound nor http.MethodOptions — those two fall back to router-level default handlers, every other method requires an explicit handler.","triggerScenarios":"Calling e.Router().Add(echo.Route{Method: http.MethodGet, Path: \"/x\"}) with Handler left nil; building a Route struct manually and forgetting the Handler field; a conditional handler that resolved to nil.","commonSituations":"Using the low-level Add API instead of e.GET/e.POST; refactors that drop the handler assignment; dynamic handler wiring that produced nil.","solutions":["Provide a non-nil Handler in the Route","Prefer the high-level helpers e.GET/e.POST which always set a handler","Use Method RouteNotFound or http.MethodOptions only when you intend the router default fallback"],"exampleFix":"// before\n_, err := e.Router().Add(echo.Route{Method: http.MethodGet, Path: \"/x\"})\n// after\n_, err := e.Router().Add(echo.Route{Method: http.MethodGet, Path: \"/x\", Handler: h})","handlingStrategy":"validation","validationCode":"if route.Handler == nil && route.Method != echo.RouteNotFound && route.Method != http.MethodOptions {\n    return errors.New(\"handler required for method \" + route.Method)\n}\n_, err := e.Router().Add(route)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer e.GET/e.POST over Router.Add","Assert Handler != nil before Add when handlers are built dynamically"],"tags":["routing","configuration"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}