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

  1. Populate ReturnInfoLoadConfig with a valid *proc.LoadConfig before issuing the Call command
  2. Use a LoadConfig matching your evaluation needs (e.g. FollowPointers, MaxVariableRecurse, MaxStringLen, MaxStructFields)
  3. 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

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


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/3dfb92b969de73b7. Report an issue: GitHub.