dagger/dagger · error
implicit input %q resolved to nil
Error message
implicit input %q resolved to nil
What it means
An ImplicitInput resolver completed without error but returned a nil Input value. dagql requires implicit inputs to resolve to a concrete value because they are attached to every cached call; a nil would be meaningless as a cache key/argument, so the call is rejected (dagql/objects.go:982).
Source
Thrown at dagql/objects.go:982
def.Directives = append(def.Directives, experimental(spec.ExperimentalReason))
}
return def
}
func (spec *FieldSpec) resolveImplicitInputCallArgs(ctx context.Context, inputArgs map[string]Input) ([]*ResultCallArg, error) {
if spec == nil || len(spec.ImplicitInputs) == 0 {
return nil, nil
}
inputIdxByName := make(map[string]int, len(spec.ImplicitInputs))
implicitArgs := make([]*ResultCallArg, 0, len(spec.ImplicitInputs))
for _, implicitInput := range spec.ImplicitInputs {
inputVal, err := implicitInput.Resolver(ctx, inputArgs)
if err != nil {
return nil, fmt.Errorf("resolve implicit input %q: %w", implicitInput.Name, err)
}
if inputVal == nil {
return nil, fmt.Errorf("implicit input %q resolved to nil", implicitInput.Name)
}
newInput, err := resultCallArgFromInput(ctx, implicitInput.Name, inputVal, false)
if err != nil {
return nil, fmt.Errorf("resolve implicit input %q: %w", implicitInput.Name, err)
}
if idx, ok := inputIdxByName[implicitInput.Name]; ok {
implicitArgs[idx] = newInput
continue
}
inputIdxByName[implicitInput.Name] = len(implicitArgs)
implicitArgs = append(implicitArgs, newInput)
}
sort.Slice(implicitArgs, func(i, j int) bool {
return implicitArgs[i].Name < implicitArgs[j].Name
})
return implicitArgs, nil
}View on GitHub (pinned to 82ba2681db)
Solutions
- Change the resolver to return a valid default Input when the underlying value is absent.
- Explicitly return an error instead of (nil, nil) when the value genuinely cannot be resolved, so the message is actionable.
- If using a typed pointer, ensure you convert it to a non-nil typed Input value before returning.
Example fix
// before
func resolve(ctx context.Context, args InputArgs) (Input, error) {
v := lookup(ctx)
return v, nil // nil when lookup fails
}
// after
func resolve(ctx context.Context, args InputArgs) (Input, error) {
v := lookup(ctx)
if v == nil { return dagql.String("default"), nil }
return v, nil
} Defensive patterns
Strategy: validation
Validate before calling
val, err := resolver(ctx, args)
if err != nil { return err }
if val == nil { return fmt.Errorf("implicit input %q resolved to nil", name) } Prevention
- Never return (nil, nil) from an ImplicitInput Resolver; return a default or an error.
- Prefer value types over typed-nil pointers for implicit inputs.
- Add a table test asserting every registered ImplicitInput resolves non-nil in a default context.
When it happens
Trigger: A custom ImplicitInput whose Resolver returns `nil, nil` — e.g. an optional implicit value where the author forgot to return a typed default when the value is absent.
Common situations: Implicit inputs keyed on optional context data (current directory, client version) where lookup silently yields nothing; mis-typed nil return of a typed nil pointer vs untyped nil interface.
Related errors
- resolve implicit input %q: %w
- cannot convert %T to a Typed value
- slice elem %d: %w
- before ID: %w
- after ID: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/4043110638854bc8.
Report an issue: GitHub.