gofiber/fiber · error
route handler 'fn' cannot be nil
Error message
route handler 'fn' cannot be nil
What it means
Group.Route(prefix, fn, name...) requires a non-nil callback that registers routes inside the newly created sub-group. A nil fn is rejected up front because silently building an empty group would mask a bug in the caller's route-registration logic. The check precedes group construction.
Solutions
- Always pass a non-nil func literal: grp.Route(prefix, func(r fiber.Router) { ... }).
- Guard the call site when the callback may be absent: if fn != nil { grp.Route(prefix, fn) }.
- Default uninitialized route-builder variables to func(fiber.Router) {} instead of nil.
Example fix
// before
var fn func(router Router)
if enableAdmin { fn = adminRoutes }
grp.Route("/admin", fn)
// after
if fn != nil {
grp.Route("/admin", fn)
} Defensive patterns
Strategy: validation
Validate before calling
if routeBuilder == nil {
return errors.New("route builder callback must not be nil")
}
grp.Route("/v1", routeBuilder) Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("Route fn nil: %v", r)
}
}()
grp.Route("/v1", fn) Prevention
- Initialize route-builder variables to func(Router) {} instead of nil.
- Always pass a func literal when possible.
- Add a nil check at any wrapper that forwards a callback to Route.
When it happens
Trigger: Calling grp.Route("/v1", nil) — the callback is nil because it was conditionally assigned, came from an unset variable, or was passed through from a wrapper that did not validate it.
Common situations: Conditional route registration (var fn func(fiber.Router); if flag { fn = ... }; grp.Route(prefix, fn)) hitting the unset branch; refactoring that leaves an unresolved callback; calling Route in a loop where some iterations have nothing to register.
Related errors
- route handler 'fn' cannot be nil
- route handler 'fn' cannot be nil
- use: invalid handler
- Domain pattern cannot be empty
- Domain pattern ' ' contains empty label at position
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/1f4d33d6d4962a89.
Report an issue: GitHub.
Appendix: source
Thrown at group.go:243
matcher: parseDomainPattern(host),
}
}
// RouteChain creates a Registering instance scoped to the group's prefix,
// allowing chained route declarations for the same path.
func (grp *Group) RouteChain(path string) Register {
// Create new group
register := &Registering{app: grp.app, group: grp, path: getGroupPath(grp.Prefix, path)}
return register
}
// Route is used to define routes with a common prefix inside the supplied
// function. It mirrors the legacy helper and reuses the Group method to create
// a sub-router.
func (grp *Group) Route(prefix string, fn func(router Router), name ...string) Router {
if fn == nil {
panic("route handler 'fn' cannot be nil")
}
// Create new group
group := grp.Group(prefix)
if len(name) > 0 {
group.Name(name[0])
}
// Define routes
fn(group)
return group
}
View on GitHub (pinned to a105acad6c)