kataras/iris · error

binder: Singleton setting is set to true but struct has dyna

Error message

binder: Singleton setting is set to true but struct has dynamic bindings: %s

What it means

The hero dependency-injection binder panics when a struct is registered with Singleton lifetime but its fields use dynamic bindings (bindings that can produce different values per resolution, such as non-singleton dependencies). A singleton cannot be safely cached if its contents depend on per-request bindings, so the library refuses the combination at registration time (hero/struct.go:109, in makeStruct).

Source

Thrown at hero/struct.go:109

				if err == ErrSeeOther {
					continue
				}

				panic(err)
			}

			elem.FieldByIndex(b.Input.StructFieldIndex).Set(input)
		} else if !b.Dependency.Static {
			if disableStructDynamicBindings {
				panic(fmt.Sprintf("binder: DisableStructDynamicBindings setting is set to true: dynamic binding found: %s", b.String()))
			}

			singleton = false
		}
	}

	if isSingleton && !singleton {
		panic(fmt.Sprintf("binder: Singleton setting is set to true but struct has dynamic bindings: %s", typ))
	}

	s := &Struct{
		ptrValue:    v,
		ptrType:     typ,
		elementType: elem.Type(),
		bindings:    bindings,
		Singleton:   singleton,
	}

	isErrHandler := isErrorHandler(typ)
	newContainer := c.Clone()
	newContainer.fillReport(typ.String(), bindings)
	// Add the controller dependency itself as func dependency but with a known type which should be explicit binding
	// in order to keep its maximum priority.
	newContainer.Register(s.Acquire).Explicitly().DestType = typ

	newContainer.GetErrorHandler = func(ctx *context.Context) ErrorHandler {

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Make the struct non-singleton (remove Singleton() or set it to false) so it is built per request.
  2. Change the dynamic bindings used by the struct's fields to singleton/static bindings so the struct can be safely cached.
  3. Move the dynamic dependency out of the struct fields and resolve it inside handler method parameters instead.
  4. Restructure so the singleton struct holds only immutable/static dependencies and wrap dynamic state in a separate request-scoped service.

Example fix

// before
binder := hero.New(hero.Struct(MyController{}, true /* singleton */))
// MyController has a field of a dynamically-bound type

// after
binder := hero.New(hero.Struct(MyController{}, false))
// or: bind the field's type as a singleton too
Defensive patterns

Strategy: validation

Validate before calling

// Before registering, ensure all field bindings are singleton/static
// or register without singleton:
binder := hero.New()
if usesDynamicBindings(MyController{}) {
    binder.Register(MyController{}) // not singleton
} else {
    binder.Singleton = true
    binder.Register(MyController{})
}

Try / catch

// Panics are not recoverable per-handler; run registration inside a guarded init:
func initBinder() (b *hero.Binder) {
    defer func() {
        if r := recover(); r != nil {
            log.Fatalf("binder config invalid: %v", r)
        }
    }()
    return hero.New(hero.Struct(MyController{}, true))
}

Prevention

When it happens

Trigger: Calling Struct(...) (via hero.New / hero.Struct) on a type marked as singleton whose exported fields are bound with dynamic bindings — e.g. bindings created from non-singleton dependency functions or explicit Binding values that are not static.

Common situations: Developers register a controller struct with .Singleton() (or use default singleton behavior) while one of its fields is a type bound dynamically, often after adding a new field with a request-scoped dependency like *context.Context or a per-request service.

Related errors


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