{"record":{"id":"fe9958b12f12084a","repo":"kataras/iris","slug":"handleerror-input-argument-must-be-a-type-of-func","errorCode":null,"errorMessage":"HandleError input argument must be a type of func(iris.Context, int, error) but got: %T","messagePattern":"HandleError input argument must be a type of func\\(iris\\.Context, int, error\\) but got: %T","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"macro/handler/handler.go","lineNumber":50,"sourceCode":"// then it returns false.\nfunc CanMakeHandler(tmpl macro.Template) (needsMacroHandler bool) {\n\tif len(tmpl.Params) == 0 {\n\t\treturn\n\t}\n\n\t// check if we have params like: {name:string} or {name} or {anything:path} without else keyword or any functions used inside these params.\n\t// 1. if we don't have, then we don't need to add a handler before the main route's handler (as I said, no performance if macro is not really used)\n\t// 2. if we don't have any named params then we don't need a handler too.\n\tfor i := range tmpl.Params {\n\t\tp := tmpl.Params[i]\n\t\tif p.CanEval() {\n\t\t\t// if at least one needs it, then create the handler.\n\t\t\tneedsMacroHandler = true\n\n\t\t\tif p.HandleError != nil {\n\t\t\t\t// Check for its type.\n\t\t\t\tif _, ok := p.HandleError.(ParamErrorHandler); !ok {\n\t\t\t\t\tpanic(fmt.Sprintf(\"HandleError input argument must be a type of func(iris.Context, int, error) but got: %T\", p.HandleError))\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn\n}\n\n// MakeHandler creates and returns a handler from a macro template, the handler evaluates each of the parameters if necessary at all.\n// If the template does not contain any dynamic attributes and a special handler is NOT required\n// then it returns a nil handler.\nfunc MakeHandler(tmpl macro.Template) context.Handler {\n\tfilter := MakeFilter(tmpl)\n\n\treturn func(ctx *context.Context) {\n\t\tif !filter(ctx) {\n\t\t\tif ctx.GetCurrentRoute().StatusErrorCode() == ctx.GetStatusCode() {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/macro/handler/handler.go#L32-L68","documentation":"macro/handler.CanMakeHandler panics when a macro template parameter's HandleError field is set but is not of the required ParamErrorHandler type, func(iris.Context, int, error) (macro/handler/handler.go:50). The type check happens before the handler is ever used, so a wrong function signature fails immediately at route/filter creation.","triggerScenarios":"Assigning a function with any signature other than func(iris.Context, int, error) to macro/param HandleError, then calling MakeFilter (or TestCanMakeHandler) which invokes CanMakeHandler.","commonSituations":"Developers write HandleError: func(ctx iris.Context, err error) forgetting the int (parameter index) argument, or pass a custom error handler wrapped in a struct.","solutions":["Change HandleError to exactly the signature func(ctx iris.Context, paramIndex int, err error).","If extra context is needed, capture it in a closure: func(ctx iris.Context, i int, err error) { ... } wrapping your logic.","Remove the HandleError field if custom param-error handling is not required."],"exampleFix":"// before\nHandleError: func(ctx iris.Context, err error) { ... }\n\n// after\nHandleError: func(ctx iris.Context, paramIndex int, err error) { ... }","handlingStrategy":"type-guard","validationCode":"// Verify the signature before assigning\nvar he interface{} = myHandler\nif _, ok := he.(macro.ParamErrorHandler); !ok {\n    panic(\"HandleError must be func(iris.Context, int, error)\")\n}","typeGuard":"func validParamErrorHandler(f interface{}) bool {\n    _, ok := f.(func(iris.Context, int, error))\n    return ok\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"invalid macro HandleError: %v\", r)\n    }\n}()","preventionTips":["Copy the ParamErrorHandler signature from the library docs exactly.","Define HandleError with named args func(ctx iris.Context, paramIndex int, err error) to keep the shape obvious.","Never wrap the handler in a custom struct type."],"tags":["go","panic","type-mismatch","routing"],"backgroundTag":"wrong-handler-signature","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}