kataras/iris · error

bindings: unresolved: no a func type: %#+v

Error message

bindings: unresolved: no a func type: %#+v

What it means

This panic comes from hero's dependency-injection container when getBindingsForFunc is asked to build input bindings for a value that is not a function. The library's handler/dependency resolution pipeline only accepts reflect.Value wrappers around func types, so it panics with 'bindings: unresolved: no a func type' to fail fast at registration time rather than at request time.

Source

Thrown at hero/binding.go:256

		}
	}

	return
}

func isPayloadType(in reflect.Type) bool {
	switch indirectType(in).Kind() {
	case reflect.Struct, reflect.Slice, reflect.Ptr:
		return true
	default:
		return false
	}
}

func getBindingsForFunc(fn reflect.Value, dependencies []*Dependency, disablePayloadAutoBinding bool, paramsCount int) []*binding {
	fnTyp := fn.Type()
	if !isFunc(fnTyp) {
		panic(fmt.Sprintf("bindings: unresolved: no a func type: %#+v", fn))
	}

	n := fnTyp.NumIn()
	inputs := make([]reflect.Type, n)
	for i := 0; i < n; i++ {
		inputs[i] = fnTyp.In(i)
	}

	bindings := getBindingsFor(inputs, dependencies, disablePayloadAutoBinding, paramsCount)
	if expected, got := n, len(bindings); expected != got {
		expectedInputs := ""
		missingInputs := ""
		for i, in := range inputs {
			pos := i + 1
			typName := in.String()
			expectedInputs += fmt.Sprintf("\n  - [%d] %s", pos, typName)
			found := false
			for _, b := range bindings {

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Verify the value passed to the container/handler registration is actually a func: pass ctrl.HandlerName (method value), not ctrl.
  2. If it is a variable, check it is not the zero value (nil func or non-func type) before registration.
  3. Use reflect to confirm: reflect.ValueOf(v).Kind() == reflect.Func before registering.
  4. If you intended to register a struct (controller), use the struct registration API (Container.Controller / hero.Struct) instead of the handler API.
  5. If nil, initialize the handler before registration.

Example fix

// before
app.Party("/").Handler(myController) // myController is a struct, not a func
// after
app.Party("/").Handler(myController.ServeHTTP) // pass the method value (a func)
Defensive patterns

Strategy: validation

Validate before calling

func isFuncHandler(v any) bool {
    if v == nil { return false }
    rv := reflect.ValueOf(v)
    return rv.Kind() == reflect.Func
}
// before registering: if !isFuncHandler(handler) { log.Fatalf("handler %T is not a func", handler) }

Type guard

func asFuncHandler(v any) (reflect.Value, bool) {
    rv := reflect.ValueOf(v)
    if rv.Kind() != reflect.Func { return reflect.Value{}, false }
    return rv, true
}

Prevention

When it happens

Trigger: Calling Container.Handler / hero.Register (which route into makeHandler -> getBindingsForFunc) with a non-func value, e.g. a struct value instead of a struct method value, a nil handler, or passing a plain object where a func was expected; also calling fromDependentFunc with a field that is not a func.

Common situations: Typos where a variable holding the handler is shadowed by a non-func value; registering an interface-typed value that is nil; refactoring a handler from a func to a struct method and forgetting to pass the bound method (e.g. passing ctrl instead of ctrl.Handler); upgrading Iris/hero versions where the API now expects a func handler value.

Related errors


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