go-delve/delve · error

LR register is nil during stack switch

Error message

LR register is nil during stack switch

What it means

On architectures that use a link register (arm64, ppc64le, riscv64, loong64, and 386 on some paths) the return address lives in the LR register. When switching to the goroutine stack, Delve must write g.LR into the LR register; if the register set has no LR slot the switch fails because the return address cannot be restored.

Source

Thrown at pkg/proc/stack.go:356

	it.top = false
	it.pc = it.frame.Ret
	it.regs = callFrameRegs
	return true
}

func (it *stackIterator) switchToGoroutineStack() error {
	if it.g == nil {
		return fmt.Errorf("nil goroutine when attempting to switch to goroutine stack")
	}
	it.systemstack = false
	it.top = false
	it.pc = it.g.PC
	it.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g.SP
	it.regs.AddReg(it.regs.BPRegNum, op.DwarfRegisterFromUint64(it.g.BP))
	if it.bi.Arch.usesLR {
		lrReg := it.regs.Reg(it.regs.LRRegNum)
		if lrReg == nil {
			return fmt.Errorf("LR register is nil during stack switch")
		}
		lrReg.Uint64Val = it.g.LR
	}
	return nil
}

// Frame returns the frame the iterator is pointing at.
func (it *stackIterator) Frame() Stackframe {
	it.frame.Bottom = it.atend
	return it.frame
}

// Err returns the error encountered during stack iteration.
func (it *stackIterator) Err() error {
	return it.err
}

// frameBase calculates the frame base pseudo-register for DWARF for fn and

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Update Delve to the latest version (arch-specific register handling fixes land frequently)
  2. Re-collect registers with a fresh stop of the thread
  3. Check DWARF info integrity of the binary (rebuild without -ldflags "-s -w")
  4. File a bug with the Go version, OS/arch, and stack dump if reproducible

Example fix

null
Defensive patterns

Strategy: type-guard

Validate before calling

if bi.Arch.usesLR && it.regs.Reg(it.regs.LRRegNum) == nil { return errors.New("register set incomplete: LR missing") }

Type guard

func hasLR(regs op.DwarfRegisters, arch proc.Arch) bool { return !arch.usesLR || regs.Reg(regs.LRRegNum) != nil }

Try / catch

err := iterateStack(g); if err != nil && strings.Contains(err.Error(), "LR register is nil") { /* re-collect registers via fresh stop before retry */ }

Prevention

When it happens

Trigger: switchToGoroutineStack called on an usesLR architecture where the DWARF register set (it.regs) lacks an entry for the LR register number — usually after register set was reconstructed from incomplete DWARF rules or a broken context.

Common situations: Debugging on ARM64/PPC64LE/RISCV64 when register reconstruction skipped LR (e.g. certain DWARF CFI edge cases, leaf-function optimizations); corrupted or minimal register context from a core dump; Delve arch/DWARF mismatches after Go runtime updates.

Related errors


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