kataras/iris · error

remove handler: unexpected type of %T

Error message

remove handler: unexpected type of %T

What it means

Route.RemoveHandler removes handlers from a route's begin, main, and done handler chains, identifying them either by name (string) or by the handler itself (context.Handler). Any other argument type hits the type-switch default and panics with the offending type via %T. It is the route-level counterpart of the APIBuilder.RemoveHandler guard.

Source

Thrown at core/router/route.go:166

func (r *Route) UseOnce(handlers ...context.Handler) {
	r.beginHandlers = context.UpsertHandlers(r.beginHandlers, handlers)
}

// RemoveHandler deletes a handler from begin, main and done handlers
// based on its name or the handler pc function.
// Returns the total amount of handlers removed.
//
// Should be called before Application Build.
func (r *Route) RemoveHandler(namesOrHandlers ...any) (count int) {
	for _, nameOrHandler := range namesOrHandlers {
		handlerName := ""
		switch h := nameOrHandler.(type) {
		case string:
			handlerName = h
		case context.Handler: //, func(*context.Context):
			handlerName = context.HandlerName(h)
		default:
			panic(fmt.Sprintf("remove handler: unexpected type of %T", h))
		}

		r.beginHandlers = removeHandler(handlerName, r.beginHandlers, &count)
		r.Handlers = removeHandler(handlerName, r.Handlers, &count)
		r.doneHandlers = removeHandler(handlerName, r.doneHandlers, &count)
	}

	return
}

func removeHandler(handlerName string, handlers context.Handlers, counter *int) (newHandlers context.Handlers) {
	for _, h := range handlers {
		if h == nil {
			continue
		}

		if context.HandlerName(h) == handlerName {
			if counter != nil {

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Pass the exact string handler name used at registration
  2. Or pass the handler as context.Handler (cast: iris/context.Handler(myFunc))
  3. Note Route.RemoveHandler does not accept *int counters — use name or handler only

Example fix

// before
route.RemoveHandler(func(ctx *context.Context) { ... }) // panics: unexpected type
// after
route.RemoveHandler("myHandlerName") // or
route.RemoveHandler(context.Handler(myHandler))
Defensive patterns

Strategy: type-guard

Validate before calling

func canRemoveRouteHandler(v any) bool {
    switch v.(type) {
    case string, context.Handler:
        return true
    default:
        return false
    }
}

Type guard

func isRouteRemoveArg(v any) bool {
    switch v.(type) {
    case string, context.Handler:
        return true
    default:
        return false
    }
}

Try / catch

func removeRouteHandlerSafe(route *router.Route, arg any) {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("Route.RemoveHandler panicked: %v (arg %T)", r, arg)
        }
    }()
    if !isRouteRemoveArg(arg) {
        log.Printf("skip: unsupported arg type %T", arg)
        return
    }
    route.RemoveHandler(arg)
}

Prevention

When it happens

Trigger: Calling Route.RemoveHandler with an unsupported value, e.g. a raw func(*context.Context) not typed as context.Handler, an int/other value, or a nil interface without a concrete type in the switch.

Common situations: Fetching routes via app.GetRoute(...) and removing handlers with a function value obtained from reflection or generics that lost its context.Handler type; passing handler names as non-string values; porting code from APIBuilder.RemoveHandler where *int counter was allowed but is not handled here.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/c615473c5f149b3e. Report an issue: GitHub.