go-delve/delve · error
can not call function with nil ReturnInfoLoadConfig
Error message
can not call function with nil ReturnInfoLoadConfig
What it means
When injecting a function call (call command), Delve needs a ReturnInfoLoadConfig to know how to read the return value's variables/types from the stopped target. This error is thrown by Command when a Call command is issued with a nil ReturnInfoLoadConfig, because return values could not be loaded afterwards.
Source
Thrown at service/debugger/debugger.go:1149
}
switch command.Name {
case api.Continue:
d.log.Debug("continuing")
if err := d.target.ChangeDirection(proc.Forward); err != nil {
return nil, err
}
err = d.target.Continue()
case api.DirectionCongruentContinue:
d.log.Debug("continuing (direction congruent)")
err = d.target.Continue()
case api.Call:
d.log.Debugf("function call %s", command.Expr)
if err := d.target.ChangeDirection(proc.Forward); err != nil {
return nil, err
}
if command.ReturnInfoLoadConfig == nil {
return nil, errors.New("can not call function with nil ReturnInfoLoadConfig")
}
g := d.target.Selected.SelectedGoroutine()
if command.GoroutineID > 0 {
g, err = proc.FindGoroutine(d.target.Selected, command.GoroutineID)
if err != nil {
return nil, err
}
}
err = proc.EvalExpressionWithCalls(d.target, g, command.Expr, *api.LoadConfigToProc(command.ReturnInfoLoadConfig), !command.UnsafeCall)
case api.Rewind:
d.log.Debug("rewinding")
if err := d.target.ChangeDirection(proc.Backward); err != nil {
return nil, err
}
err = d.target.Continue()
case api.Next:
d.log.Debug("nexting")
if err := d.target.ChangeDirection(proc.Forward); err != nil {View on GitHub (pinned to a23773e6c3)
Solutions
- Populate ReturnInfoLoadConfig with a valid *proc.LoadConfig before issuing the Call command
- Use a LoadConfig matching your evaluation needs (e.g. FollowPointers, MaxVariableRecurse, MaxStringLen, MaxStructFields)
- Upgrade/fix the calling frontend so it always sets the field for call commands
Example fix
// before
cmd := &api.DebuggerCommand{Name: api.Call, Expr: "fmt.Println(\"hi\")"}
d.Command(cmd, out)
// after
cmd := &api.DebuggerCommand{Name: api.Call, Expr: "fmt.Println(\"hi\")",
ReturnInfoLoadConfig: &proc.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1}}
d.Command(cmd, out) Defensive patterns
Strategy: validation
Validate before calling
if cmd.Name == api.Call && cmd.ReturnInfoLoadConfig == nil {
cmd.ReturnInfoLoadConfig = &proc.LoadConfig{
FollowPointers: true, MaxVariableRecurse: 1,
MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1,
}
} Type guard
func callCmdReady(cmd *api.DebuggerCommand) bool {
return cmd.Name != api.Call || cmd.ReturnInfoLoadConfig != nil
} Try / catch
out, err := dbg.Command(cmd, nil)
if err != nil && strings.Contains(err.Error(), "nil ReturnInfoLoadConfig") {
cmd.ReturnInfoLoadConfig = defaultLoadConfig()
out, err = dbg.Command(cmd, nil)
} Prevention
- Always construct call commands through a helper that fills LoadConfig defaults
- Keep a shared defaultLoadConfig() in client code for evaluation and calls
- Re-check struct fields after upgrading the delve API version
When it happens
Trigger: Calling Debugger.Command (RPC2 service/command) with api.DebuggerCommand{Name: api.Call, Expr: ..., ReturnInfoLoadConfig: nil} and Forward direction.
Common situations: Custom frontends or scripts invoking the RPC call API directly and forgetting to populate ReturnInfoLoadConfig; older client code written before the field was required; wrappers that copy a DebuggerCommand struct but drop nested config pointers.
Related errors
- mismatched length in addrs and addrpid
- channel filter can not be negated
- count == 0 not allowed with a channel filter
- channel filter without eval scope
- unknown API version
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/3dfb92b969de73b7.
Report an issue: GitHub.