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

  1. Always pass a non-nil func literal: grp.Route(prefix, func(r fiber.Router) { ... }).
  2. Guard the call site when the callback may be absent: if fn != nil { grp.Route(prefix, fn) }.
  3. 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

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


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)