go-delve/delve · error

could not set call receiver: %v

Error message

could not set call receiver: %v

What it means

When the injected call target is a method with a value/pointer receiver, Delve copies the receiver into the formal argument slot 0 via funcCallCopyOneArg before the call is made. If copying fails — unreadable receiver variable, unsupported type conversion, or a memory write error while placing the argument — evalCallInjectionSetTarget records "could not set call receiver: %v" on the eval stack and aborts the call injection.

Source

Thrown at pkg/proc/fncall.go:1023

	if fncall.closureAddr != 0 {
		// When calling a function pointer we must set the DX register to the
		// address of the function pointer itself.
		setClosureReg(thread, fncall.closureAddr)
	}

	undo := new(undoInjection)
	undo.oldpc = regs.PC()
	if scope.BinInfo.Arch.Name == "arm64" || scope.BinInfo.Arch.Name == "ppc64le" || scope.BinInfo.Arch.Name == "loong64" {
		undo.oldlr = regs.LR()
	}
	callOP(scope.BinInfo, thread, regs, fncall.fn.Entry)

	fncall.undoInjection = undo

	if fncall.receiver != nil {
		err := funcCallCopyOneArg(scope, fncall, fncall.receiver, &fncall.formalArgs[0], thread)
		if err != nil {
			stack.err = fmt.Errorf("could not set call receiver: %v", err)
			return
		}
		fncall.formalArgs = fncall.formalArgs[1:]
	}
}

func readStackVariable(t *Target, thread Thread, regs Registers, off uint64, typename string, loadCfg LoadConfig) (*Variable, error) {
	bi := thread.BinInfo()
	scope, err := ThreadScope(t, thread)
	if err != nil {
		return nil, err
	}
	typ, err := bi.findType(typename)
	if err != nil {
		return nil, err
	}
	v := newVariable("", regs.SP()+off, typ, scope.BinInfo, scope.Mem)
	v.loadValue(loadCfg)

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Read the wrapped cause to identify whether it is a variable-load failure or a memory write failure.
  2. Rebuild the target with -gcflags="all=-N -l" so receiver variables are not optimized out.
  3. Check the receiver is valid (non-nil pointer, initialized value) before injecting the call.
  4. Inject a call on a plain function or use a helper function that takes the receiver as an explicit argument instead.
  5. Update Delve if the receiver type (e.g. new Go struct layout) is unsupported.

Example fix

// before: receiver optimized out
func main() { u := getUser(); _ = u } // u optimized away
dlv> call u.Name()
// after: keep receiver alive and valid
func main() { u := getUser(); println(u.Name()) } // set breakpoint here
dlv> call u.Name()
Defensive patterns

Strategy: validation

Validate before calling

// before injecting a method call, verify the receiver is readable
recv, err := dbg.EvalVariable(scope, "obj", proc.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 256})
if err != nil || recv.Unreadable != nil {
    return fmt.Errorf("receiver not available for call injection")
}

Type guard

func isInjectableReceiver(v *proc.Variable) bool {
    return v != nil && v.Unreadable == nil && v.Addr != 0
}

Try / catch

if err != nil && strings.Contains(err.Error(), "could not set call receiver:") {
    // receiver copy failed: rebuild unoptimized or use a free function taking the receiver as an arg
}

Prevention

When it happens

Trigger: Evaluating a method call expression (e.g. call obj.Method(x)) where the receiver obj cannot be copied into the call frame: obj is unreadable (optimized-out, nil unsafe pointer deref during load), the receiver type mismatch, or writing the argument into the target's stack fails.

Common situations: Calling methods on variables that were optimized away by the compiler; method calls on nil pointers/maps; injecting calls in binaries built with heavy optimization (-gcflags="-N -l" missing); calling methods on interface variables whose dynamic type can't be materialized.

Related errors


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