gofiber/fiber · error

nil handler in route: %s

Error message

nil handler in route: %s

What it means

App.register iterates over every handler in the handlers slice and panics with "nil handler in route" if any single handler is nil, because a nil handler would panic at request time when the router invokes it. This guard fails fast at registration instead.

Source

Thrown at router.go:986

			continue
		}

		app.stack[headIndex] = append(headStack[:i], headStack[i+1:]...)
		app.hasRoutesRefreshed = true
		atomic.AddUint32(&app.handlersCount, ^uint32(len(headRoute.Handlers)-1)) //nolint:gosec // G115 - handler count is always small
		return
	}
}

func (app *App) register(methods []string, pathRaw string, group *Group, handlers ...Handler) {
	// A regular route requires at least one ctx handler
	if len(handlers) == 0 && group == nil {
		panic(fmt.Sprintf("missing handler/middleware in route: %s\n", pathRaw))
	}
	// No nil handlers allowed
	for _, h := range handlers {
		if h == nil {
			panic(fmt.Sprintf("nil handler in route: %s\n", pathRaw))
		}
	}

	// Precompute path normalization ONCE
	if pathRaw == "" {
		pathRaw = "/"
	}
	if pathRaw[0] != '/' {
		pathRaw = "/" + pathRaw
	}
	pathPretty := pathRaw
	if !app.config.CaseSensitive {
		pathPretty = utilsstrings.ToLower(pathPretty)
	}
	if !app.config.StrictRouting && len(pathPretty) > 1 {
		pathPretty = utils.TrimRight(pathPretty, '/')
	}
	pathClean := RemoveEscapeChar(pathPretty)

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Ensure every handler/middleware passed to a route is non-nil; filter nils out of slices before registering.
  2. Use a no-op handler (func(c fiber.Ctx) error { return c.Next() }) instead of nil for optional branches.
  3. Initialize handler variables to a concrete value rather than leaving the zero-value nil pointer.

Example fix

// before
var auth fiber.Handler
if enableAuth {
    auth = jwt.New(...)
}
app.Get("/secret", auth, secretHandler)
// after
auth := func(c fiber.Ctx) error { return c.Next() }
if enableAuth {
    auth = jwt.New(...)
}
app.Get("/secret", auth, secretHandler)
Defensive patterns

Strategy: validation

Validate before calling

filtered := handlers[:0]
for _, h := range handlers {
    if h != nil {
        filtered = append(filtered, h)
    }
}
if len(filtered) < len(handlers) {
    log.Printf("route %q: dropped %d nil handler(s)", path, len(handlers)-len(filtered))
}
app.Register(methods, path, filtered...)

Type guard

func isNonNilHandler(h fiber.Handler) bool {
    return h != nil
}

Prevention

When it happens

Trigger: Registering a route where one of the variadic handler arguments is a nil fiber.Handler, e.g. app.Get("/x", realHandler, nil). Common when a handler variable is conditionally assigned and ends up nil.

Common situations: Conditionally including a middleware (var mw fiber.Handler; if cond { mw = ... }) and passing mw when the condition is false. A handler slice built by appending optional middlewares that include nil. Refactoring that leaves a nil in a handler chain.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/a427a551eea7adf5.json. Report an issue: GitHub.