kataras/iris · error

bad value: function has zero outputs

Error message

bad value: function has zero outputs

What it means

A dependency function must return at least one value — the dependency itself. A function with zero return values provides nothing the container can inject, so fromFunc panics.

Source

Thrown at hero/dependency.go:291

	typ := v.Type()
	numIn := typ.NumIn()
	numOut := typ.NumOut()

	if numIn == 0 {
		// it's an empty function, that must return a structure.
		if numOut != 1 {
			firstOutType := indirectType(typ.Out(0))
			if firstOutType.Kind() != reflect.Struct && firstOutType.Kind() != reflect.Interface {
				panic(fmt.Sprintf("bad value: function has zero inputs: empty input function must output a single value but got: length=%v, type[0]=%s", numOut, firstOutType.String()))
			}
		}

		// fallback to structure.
		return fromStructValue(v.Call(nil)[0], dest)
	}

	if numOut == 0 {
		panic("bad value: function has zero outputs")
	}

	if numOut == 2 && !isError(typ.Out(1)) {
		panic("bad value: second output should be an error")
	}

	if numOut > 2 {
		// - at least one output value
		// - maximum of two output values
		// - second output value should be a type of error.
		panic(fmt.Sprintf("bad value: function has invalid number of output arguments: %v", numOut))
	}

	var handler DependencyHandler

	firstIsContext := isContext(typ.In(0))
	secondIsInput := numIn == 2 && typ.In(1) == inputTyp
	onlyContext := (numIn == 1 && firstIsContext) || (numIn == 2 && firstIsContext && typ.IsVariadic())

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Add a return value: have the function return the dependency (and optionally an error).
  2. If the function is purely for side effects, run it yourself and register its result instead.
  3. Convert: func(cfg *Config) { svc = build(cfg) } → func(cfg *Config) *Svc { return build(cfg) } and register that.

Example fix

// before
func setup(cfg *Config) { /* no return */ }
c.Register(setup)
// after
func setup(cfg *Config) *App { return buildApp(cfg) }
c.Register(setup)
Defensive patterns

Strategy: validation

Validate before calling

func hasOutput(fn any) bool { return reflect.TypeOf(fn).NumOut() > 0 }

Try / catch

func() { defer func() { if r := recover(); r != nil { log.Printf("bad dependency: %v", r) } }()
	c.Register(fn) }()

Prevention

When it happens

Trigger: Registering a func(...) with no return values, e.g. func(cfg *Config) { ... } that only performs side effects, via c.Register / NewDependency.

Common situations: Passing an initializer/setup function (which mutates globals) instead of a factory function; accidentally registering a method that returns nothing; after a refactor removed the return value.

Related errors


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