kataras/iris · error
bad value: nil: %T
Error message
bad value: nil: %T
What it means
newDependency normalizes any user-supplied dependency (static value, struct, or resolving func) into a *Dependency. If the supplied value is nil (nil interface or typed-nil that valueOf turns into an invalid value), hero cannot represent it and panics immediately with 'bad value: nil'. This is a registration-time guard so bad dependency declarations fail at startup.
Source
Thrown at hero/dependency.go:90
return fmt.Sprintf("%s (%#+v)", sourceLine, val)
}
// NewDependency converts a function or a function which accepts other dependencies or static struct value to a *Dependency.
//
// See `Container.Handler` for more.
func NewDependency(dependency any, funcDependencies ...*Dependency) *Dependency { // used only on tests.
return newDependency(dependency, false, false, nil, funcDependencies...)
}
func newDependency(
dependency any,
disablePayloadAutoBinding bool,
enableStructDependents bool,
matchDependency DependencyMatcher,
funcDependencies ...*Dependency,
) *Dependency {
if dependency == nil {
panic(fmt.Sprintf("bad value: nil: %T", dependency))
}
if d, ok := dependency.(*Dependency); ok {
// already a *Dependency, do not continue (and most importatly do not call resolveDependency) .
return d
}
v := valueOf(dependency)
if !goodVal(v) {
panic(fmt.Sprintf("bad value: %#+v", dependency))
}
if matchDependency == nil {
matchDependency = DefaultDependencyMatcher
}
dest := &Dependency{
Source: newSource(v),View on GitHub (pinned to 7bedaf55a0)
Solutions
- Ensure the dependency value is initialized before registration: create the service instance (e.g. NewService()) rather than passing its nil pointer.
- Add a nil check before calling Register: if svc == nil { panic/log } then register.
- Return an error early from config loading instead of nil, so registration never sees nil.
- If the dependency is genuinely optional, do not register it; let hero resolve other bindings.
- Register a factory func (func() *Service) that builds the value lazily instead of a nil static value.
Example fix
// before
var svc *MyService
container.Register(svc) // panics: bad value: nil
// after
container.Register(func() *MyService { return NewMyService() }) Defensive patterns
Strategy: validation
Validate before calling
func mustRegister(c *hero.Container, dep any) {
if dep == nil || reflect.ValueOf(dep).IsZero() {
panic(fmt.Sprintf("refusing to register nil dependency %T", dep))
}
c.Register(dep)
} Type guard
func isNonNil(v any) bool {
if v == nil { return false }
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Ptr, reflect.Interface, reflect.Map, reflect.Slice, reflect.Func, reflect.Chan:
return !rv.IsNil()
default:
return true
}
} Try / catch
func safeRegister(dep any) (ok bool) {
defer func() {
if r := recover(); r != nil {
if s, isStr := r.(string); isStr && strings.Contains(s, "bad value") {
log.Printf("dependency registration failed: %s", s)
} else { panic(r) }
}
}()
container.Register(dep)
return true
} Prevention
- Never register variables that may be nil; register factory funcs (func() *Service) instead.
- Validate config/env loading completes and produces non-nil services before DI wiring.
- Use constructor functions that panic early on unresolvable dependencies, keeping nils out of the graph.
- Add a startup integration test that performs all container.Register calls so nils fail in CI.
When it happens
Trigger: Calling Container.Register(nil), hero.NewDependency(nil), or NewDependency(nil) directly; registering a variable that is a nil *Dependency; a struct field whose value is a nil interface being fed into newDependency via getBindingsForStruct's nonZero field handling; passing a typed nil (e.g. (*Service)(nil)) that fails goodVal and surfaces the nil/bad-value path.
Common situations: A config/env loader returning nil before wiring dependencies; refactors where the dependency variable became a nil pointer; forgetting to initialize a service before container.Register(svc); map lookups returning a nil value passed straight to Register.
Related errors
- bad value: %#+v
- 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
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/5053ee69531980a0.
Report an issue: GitHub.