{"record":{"id":"c615473c5f149b3e","repo":"kataras/iris","slug":"remove-handler-unexpected-type-of-t-c61547","errorCode":null,"errorMessage":"remove handler: unexpected type of %T","messagePattern":"remove handler: unexpected type of %T","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/router/route.go","lineNumber":166,"sourceCode":"func (r *Route) UseOnce(handlers ...context.Handler) {\n\tr.beginHandlers = context.UpsertHandlers(r.beginHandlers, handlers)\n}\n\n// RemoveHandler deletes a handler from begin, main and done handlers\n// based on its name or the handler pc function.\n// Returns the total amount of handlers removed.\n//\n// Should be called before Application Build.\nfunc (r *Route) RemoveHandler(namesOrHandlers ...any) (count int) {\n\tfor _, nameOrHandler := range namesOrHandlers {\n\t\thandlerName := \"\"\n\t\tswitch h := nameOrHandler.(type) {\n\t\tcase string:\n\t\t\thandlerName = h\n\t\tcase context.Handler: //, func(*context.Context):\n\t\t\thandlerName = context.HandlerName(h)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"remove handler: unexpected type of %T\", h))\n\t\t}\n\n\t\tr.beginHandlers = removeHandler(handlerName, r.beginHandlers, &count)\n\t\tr.Handlers = removeHandler(handlerName, r.Handlers, &count)\n\t\tr.doneHandlers = removeHandler(handlerName, r.doneHandlers, &count)\n\t}\n\n\treturn\n}\n\nfunc removeHandler(handlerName string, handlers context.Handlers, counter *int) (newHandlers context.Handlers) {\n\tfor _, h := range handlers {\n\t\tif h == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif context.HandlerName(h) == handlerName {\n\t\t\tif counter != nil {","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/core/router/route.go#L148-L184","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass the exact string handler name used at registration","Or pass the handler as context.Handler (cast: iris/context.Handler(myFunc))","Note Route.RemoveHandler does not accept *int counters — use name or handler only"],"exampleFix":"// before\nroute.RemoveHandler(func(ctx *context.Context) { ... }) // panics: unexpected type\n// after\nroute.RemoveHandler(\"myHandlerName\") // or\nroute.RemoveHandler(context.Handler(myHandler))","handlingStrategy":"type-guard","validationCode":"func canRemoveRouteHandler(v any) bool {\n    switch v.(type) {\n    case string, context.Handler:\n        return true\n    default:\n        return false\n    }\n}","typeGuard":"func isRouteRemoveArg(v any) bool {\n    switch v.(type) {\n    case string, context.Handler:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"func removeRouteHandlerSafe(route *router.Route, arg any) {\n    defer func() {\n        if r := recover(); r != nil {\n            log.Printf(\"Route.RemoveHandler panicked: %v (arg %T)\", r, arg)\n        }\n    }()\n    if !isRouteRemoveArg(arg) {\n        log.Printf(\"skip: unsupported arg type %T\", arg)\n        return\n    }\n    route.RemoveHandler(arg)\n}","preventionTips":["Pass the handler's registered string name whenever possible","Cast function values explicitly to iris/context.Handler before removal","Do not pass *int counters here — that is only supported at the APIBuilder level","Keep handler names as constants to avoid name/type drift during refactors"],"tags":["panic","type-mismatch","routing","middleware"],"backgroundTag":"unsupported-argument-type","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}