kataras/iris · error
HandleError input argument must be a type of func(iris.Conte
Error message
HandleError input argument must be a type of func(iris.Context, int, error) but got: %T
What it means
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.
Source
Thrown at macro/handler/handler.go:50
// then it returns false.
func CanMakeHandler(tmpl macro.Template) (needsMacroHandler bool) {
if len(tmpl.Params) == 0 {
return
}
// check if we have params like: {name:string} or {name} or {anything:path} without else keyword or any functions used inside these params.
// 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)
// 2. if we don't have any named params then we don't need a handler too.
for i := range tmpl.Params {
p := tmpl.Params[i]
if p.CanEval() {
// if at least one needs it, then create the handler.
needsMacroHandler = true
if p.HandleError != nil {
// Check for its type.
if _, ok := p.HandleError.(ParamErrorHandler); !ok {
panic(fmt.Sprintf("HandleError input argument must be a type of func(iris.Context, int, error) but got: %T", p.HandleError))
}
}
break
}
}
return
}
// MakeHandler creates and returns a handler from a macro template, the handler evaluates each of the parameters if necessary at all.
// If the template does not contain any dynamic attributes and a special handler is NOT required
// then it returns a nil handler.
func MakeHandler(tmpl macro.Template) context.Handler {
filter := MakeFilter(tmpl)
return func(ctx *context.Context) {
if !filter(ctx) {
if ctx.GetCurrentRoute().StatusErrorCode() == ctx.GetStatusCode() {View on GitHub (pinned to 7bedaf55a0)
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.
Example fix
// before
HandleError: func(ctx iris.Context, err error) { ... }
// after
HandleError: func(ctx iris.Context, paramIndex int, err error) { ... } Defensive patterns
Strategy: type-guard
Validate before calling
// Verify the signature before assigning
var he interface{} = myHandler
if _, ok := he.(macro.ParamErrorHandler); !ok {
panic("HandleError must be func(iris.Context, int, error)")
} Type guard
func validParamErrorHandler(f interface{}) bool {
_, ok := f.(func(iris.Context, int, error))
return ok
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("invalid macro HandleError: %v", r)
}
}() Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- iris: switch: hosts: invalid target type: %T
- <appName> is not a registered Application
- unexpected "fsOrDir" argument type of %T (string or http.Fil
- remove handler: unexpected type of %T
- remove handler: unexpected type of %T
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/fe9958b12f12084a.
Report an issue: GitHub.