gofiber/fiber · error

use: invalid handler %v

Error message

use: invalid handler %v

What it means

fiber/v3's domainRouter.Use accepts string prefixes, []string of prefixes, *App sub-apps, and handler values convertible by toFiberHandler (Fiber handlers, Express-style func(Req,Res,...), net/http handlers, fasthttp handlers). Any other type — or nil — reaches the default branch and panics with the offending type. The message prints reflect.TypeOf(arg) so you can see exactly what was passed.

Source

Thrown at domain.go:367

//	})
func (d *domainRouter) Use(args ...any) Router {
	var subApp *App
	var prefix string
	var prefixes []string
	var handlers []Handler

	for i := range args {
		switch arg := args[i].(type) {
		case string:
			prefix = arg
		case []string:
			prefixes = arg
		case *App:
			subApp = arg
		default:
			handler, ok := toFiberHandler(arg)
			if !ok {
				panic(fmt.Sprintf("use: invalid handler %v", reflect.TypeOf(arg)))
			}
			handlers = append(handlers, handler)
		}
	}

	if len(prefixes) == 0 {
		prefixes = append(prefixes, prefix)
	}

	for _, prefix := range prefixes {
		if subApp != nil {
			return d.mount(prefix, subApp)
		}

		wrapped := d.wrapHandlers(handlers)
		d.app.register([]string{methodUse}, d.registerPath(prefix), d.registerGroup(), wrapped...)
	}

View on GitHub (pinned to a105acad6c)

Solutions

  1. Check the offending argument's type (the panic prints it) and convert it to a supported handler signature — most simply fiber.Handler (func(Ctx) error).
  2. If passing a typed-nil handler, replace it with a real handler or omit it; nil values short-circuit toFiberHandler.
  3. Wrap net/http handlers with an explicit adapter or pass them directly only if their static type is exactly http.HandlerFunc/http.Handler/func(http.ResponseWriter,*http.Request).

Example fix

// before
d.Use("/api", 42)                       // int -> panic
d.Use("/api", func(c *fiber.Ctx) error{...}) // wrong: *Ctx vs interface Ctx
// after
d.Use("/api", func(c fiber.Ctx) error{ return nil })
Defensive patterns

Strategy: type-guard

Type guard

// isUseArg reports whether v is accepted by domainRouter.Use / Group.Use / App.Use.
func isUseArg(v any) bool {
    switch v.(type) {
    case string, []string, *fiber.App:
        return true
    case fiber.Handler, func(fiber.Ctx),
        func(fiber.Req, fiber.Res) error, func(fiber.Req, fiber.Res),
        func(fiber.Req, fiber.Res, func() error) error, func(fiber.Req, fiber.Res, func() error),
        func(fiber.Req, fiber.Res, func()) error, func(fiber.Req, fiber.Res, func()),
        func(fiber.Req, fiber.Res, func(error)), func(fiber.Req, fiber.Res, func(error)) error,
        func(fiber.Req, fiber.Res, func(error) error), func(fiber.Req, fiber.Res, func(error) error) error,
        http.HandlerFunc, http.Handler, func(http.ResponseWriter, *http.Request),
        fasthttp.RequestHandler, func(*fasthttp.RequestCtx) error:
        return true
    }
    return false
}

for _, a := range args {
    if !isUseArg(a) {
        return fmt.Errorf("unsupported Use arg %T", a)
    }
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Fatalf("domain Use arg rejected: %v", r)
    }
}()
d.Use(args...)

Prevention

When it happens

Trigger: Calling d.Use(...) on a domain router and passing an argument whose static type is not string, []string, or *App, and whose dynamic type is not one of the ~17 supported handler signatures — e.g. an int, a struct value, a chan, a bare nil (which has no type), or a func with an unsupported signature like func(int) error.

Common situations: Passing a typed nil (var h MyHandler = nil) that does not match any case; passing a handler with a subtly wrong signature (e.g. func(c *fiber.Ctx) when Ctx is an interface, or returning a non-error); forgetting to wrap an http.Handler; copy-paste leaving a placeholder value/zero struct in the variadic args.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/e1e0746876d6937e. Report an issue: GitHub.