kataras/iris · error

bad value: could not resolve a dependency from: %#+v

Error message

bad value: could not resolve a dependency from: %#+v

What it means

After receiving a usable value, newDependency calls resolveDependency to figure out how to produce the dependency. If resolution fails (e.g. a function input cannot be bound to any known binding), it panics saying no dependency could be resolved from the given value.

Source

Thrown at hero/dependency.go:115

	v := valueOf(dependency)
	if !goodVal(v) {
		panic(fmt.Sprintf("bad value: %#+v", dependency))
	}

	if matchDependency == nil {
		matchDependency = DefaultDependencyMatcher
	}

	dest := &Dependency{
		Source:           newSource(v),
		OriginalValue:    dependency,
		StructDependents: enableStructDependents,
	}
	dest.Match = ToDependencyMatchFunc(dest, matchDependency)

	if !resolveDependency(v, disablePayloadAutoBinding, dest, funcDependencies...) {
		panic(fmt.Sprintf("bad value: could not resolve a dependency from: %#+v", dependency))
	}

	return dest
}

// DependencyResolver func(v reflect.Value, dest *Dependency) bool
// Resolver     DependencyResolver

func resolveDependency(v reflect.Value, disablePayloadAutoBinding bool, dest *Dependency, prevDependencies ...*Dependency) bool {
	return fromDependencyHandler(v, dest) ||
		fromBuiltinValue(v, dest) ||
		fromStructValueOrDependentStructValue(v, disablePayloadAutoBinding, dest, prevDependencies) ||
		fromFunc(v, dest) ||
		len(prevDependencies) > 0 && fromDependentFunc(v, disablePayloadAutoBinding, dest, prevDependencies)
}

func fromDependencyHandler(_ reflect.Value, dest *Dependency) bool {
	// It's already on the desired form, just return it.

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Register the missing dependency type: c.Register(myService) so the function's inputs can be resolved.
  2. Simplify the function signature so all inputs are types the container knows (or *iris.Context / context.Context).
  3. If payload auto-binding was disabled, re-enable c.DisablePayloadAutoBinding = false or register the payload type explicitly.
  4. Log/print the function signature and compare each input type against registered bindings.

Example fix

// before
func newSvc(cfg *Config) *Service { ... } // Config never registered
c.Register(newSvc)
// after
c.Register(cfg)          // register the input first
c.Register(newSvc)
Defensive patterns

Strategy: validation

Validate before calling

// Before registering a factory func, check each input type has a binding:
for _, in := range reflect.TypeOf(factoryFn).NumIn() /* iterate Ins */ {
	if !c.CanInject(inType) { panic("no binding for " + inType.String()) }
}

Type guard

func allInputsBound(fn any, bound map[reflect.Type]bool) bool {
	t := reflect.TypeOf(fn)
	for i := 0; i < t.NumIn(); i++ {
		if !bound[t.In(i)] { return false }
	}
	return true
}

Prevention

When it happens

Trigger: Registering a function whose input parameter types match no known binding (no matching registered dependency or request context type), with disablePayloadAutoBinding preventing auto-binding, via NewDependency/Register/BuiltinDependencies/getBindingsForStruct.

Common situations: A handler dependency function takes a custom type that was never registered; renaming/refactoring a service type so its registered binding no longer matches; spelling the expected input type differently from the registered one.

Related errors


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