kataras/iris · error
MarkExportedFieldsAsRequired is true and at least one of str
Error message
MarkExportedFieldsAsRequired is true and at least one of struct's (%s) field was not binded to a dependency. Fields length: %d, matched exported bindings length: %d. Use the Reporter for further details
What it means
When MarkExportedFieldsAsRequired (Container.RegisterDependency/struct registration with required exported fields) is enabled, hero insists that EVERY exported field of the struct resolves to a dependency binding. If len(exportedBindings) != len(fields), at least one exported field could not be matched, and hero panics telling you to use the Reporter for details.
Source
Thrown at hero/binding.go:335
})
}
inputs := make([]reflect.Type, n)
for i := 0; i < n; i++ {
// fmt.Printf("Controller [%s] | Field Index: %v | Field Type: %s\n", typ, fields[i].Index, fields[i].Type)
inputs[i] = fields[i].Type
}
exportedBindings := getBindingsFor(inputs, dependencies, disablePayloadAutoBinding, paramsCount)
// fmt.Printf("Controller [%s] | Inputs length: %d vs Bindings length: %d | NonZero: %d | Stateless : %d\n",
// typ, n, len(exportedBindings), len(nonZero), stateless)
// for i, b := range exportedBindings {
// fmt.Printf("[%d] [Static=%v] %#+v\n", i, b.Dependency.Static, b.Dependency.OriginalValue)
// }
if markExportedFieldsAsRequired && len(exportedBindings) != n {
panic(fmt.Sprintf("MarkExportedFieldsAsRequired is true and at least one of struct's (%s) field was not binded to a dependency.\nFields length: %d, matched exported bindings length: %d.\nUse the Reporter for further details", typ.String(), n, len(exportedBindings)))
}
if stateless == 0 && len(nonZero) >= len(exportedBindings) {
// if we have not a single stateless and fields are defined then just return.
// Note(@kataras): this can accept further improvements.
return
}
// get declared bindings from deps.
bindings = append(bindings, exportedBindings...)
for _, binding := range bindings {
// fmt.Printf(""Controller [%s] | Binding: %s\n", typ, binding.String())
if len(binding.Input.StructFieldIndex) == 0 {
// set correctly the input's field index and name.
f := fields[binding.Input.Index]
binding.Input.StructFieldIndex = f.Index
binding.Input.StructFieldName = f.NameView on GitHub (pinned to 7bedaf55a0)
Solutions
- Register a dependency for every missing exported field type, e.g. container.Register(func() *DB { return db }).
- Read the hero Reporter output (container.Report(w)) to see exactly which fields failed to bind.
- Change the field to unexported if it should not be injected, or remove it if unused.
- Fill the field with a non-zero value before registration (non-zero field values are picked up directly by lookupNonZeroFieldValues).
- Disable MarkExportedFieldsAsRequired if strict field injection is not actually needed.
Example fix
// before
type Ctx struct { DB *DB; Logger *Logger } // Logger has no dependency
container.MarkExportedFieldsAsRequired()
// after
container.Register(func() *Logger { return log.New(os.Stdout, "", 0) }) Defensive patterns
Strategy: validation
Validate before calling
// before enabling strict mode, verify each exported field type has a dependency
func checkExportedFieldsBound(v any, depTypes map[reflect.Type]bool) []reflect.Type {
var missing []reflect.Type
t := reflect.Indirect(reflect.TypeOf(v))
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.IsExported() && !depTypes[f.Type] {
missing = append(missing, f.Type)
}
}
return missing
} Type guard
func allExportedFieldsBindable(v any, depTypes map[reflect.Type]bool) bool {
return len(checkExportedFieldsBound(v, depTypes)) == 0
} Try / catch
func safeStructWithRequired(v any) (ok bool) {
defer func() {
if r := recover(); r != nil {
if s, isStr := r.(string); isStr && strings.Contains(s, "MarkExportedFieldsAsRequired") {
log.Printf("required-field binding failed: %s", s)
} else { panic(r) }
}
}()
container.Register(v)
return true
} Prevention
- Run container.Report(os.Stdout) whenever enabling MarkExportedFieldsAsRequired.
- Only enable strict required mode on structs whose every exported field is a registered dependency type.
- Keep injected fields unexported if they are optional, so strict mode skips them.
- Add a CI test constructing every strict-mode struct so new fields force a matching dependency registration.
When it happens
Trigger: Enabling MarkExportedFieldsAsRequired (e.g. Container.Require or struct registration with markExported=true) while the struct has an exported field with no matching registered dependency — e.g. a field of type *DB, a time.Time, a basic type like string/int that no dependency provides, or a field that payload-binding intentionally skips.
Common situations: Turning on strict required-field mode in an existing codebase where one struct gained a new exported field that was never registered as a dependency; fields of primitive types that DI was never meant to fill; a dependency registered for an interface while the field is the concrete type; test fixtures using TestBindingsForStructMarkExportedFieldsAsRequred style setups missing one dependency.
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
- bad value: nil: %T
- binder: struct: should be a pointer to a struct value
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/29654b9fdfb518db.
Report an issue: GitHub.