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
- Make the struct non-singleton (remove Singleton() or set it to false) so it is built per request.
- Change the dynamic bindings used by the struct's fields to singleton/static bindings so the struct can be safely cached.
- Move the dynamic dependency out of the struct fields and resolve it inside handler method parameters instead.
- 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
- Only mark structs singleton when all their field dependencies are singletons too.
- Resolve request-scoped dependencies via handler method parameters, not struct fields.
- Cover binder registration in an init-time test to surface the panic at startup.
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
- bindings: unresolved: no a func type: %#+v
- expected [%d] bindings (input parameters) but got [%d] Funct
- bindings: unresolved: not a struct type: %#+v
- MarkExportedFieldsAsRequired is true and at least one of str
- bad value: nil: %T
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/ae22d5bde54d2c44.
Report an issue: GitHub.