go-delve/delve · error

hardware breakpoints exhausted

Error message

hardware breakpoints exhausted

What it means

DebugRegisters.SetBreakpoint programs one of the x86 hardware debug registers (DR0-DR3). CPUs only provide four hardware breakpoints, so pAddrs has length 4; requesting an index >= 4 means all debug registers would be exhausted. Delve throws this instead of silently reusing or evicting an existing hardware breakpoint.

Source

Thrown at pkg/proc/amd64util/debugregs.go:63

	case 0x0:
		sz = 1
	case 0x1:
		sz = 2
	case 0x2:
		sz = 8 // sic
	case 0x3:
		sz = 4
	}
	return addr, read, write, sz
}

// SetBreakpoint sets hardware breakpoint at index 'idx' to the specified
// address, read/write flags and size.
// If the breakpoint is already in use but the parameters match it does
// nothing.
func (drs *DebugRegisters) SetBreakpoint(idx uint8, addr uint64, read, write bool, sz int) error {
	if int(idx) >= len(drs.pAddrs) {
		return errors.New("hardware breakpoints exhausted")
	}
	curaddr, curread, curwrite, cursz := drs.breakpoint(idx)
	if curaddr != 0 {
		if (curaddr != addr) || (curread != read) || (curwrite != write) || (cursz != sz) {
			return fmt.Errorf("hardware breakpoint %d already in use (address %#x)", idx, curaddr)
		}
		// hardware breakpoint already set
		return nil
	}

	if read && !write {
		return errors.New("break on read only not supported")
	}

	*(drs.pAddrs[idx]) = addr
	var lenrw uint64
	if write {
		lenrw |= 0x1

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Reduce the number of simultaneous hardware breakpoints to at most 4 per thread
  2. Clear unused hardware breakpoints (ClearBreakpoint/zeroing the debug register) before setting new ones
  3. Fall back to software breakpoints for the extra locations
  4. Check the return error of SetBreakpoint and surface 'watchpoint limit reached' to the user instead of retrying

Example fix

// before
drs.SetBreakpoint(4, addr, false, true, 8) // panics into error: exhausted
// after
const maxHW = 4
if idx >= maxHW { return fmt.Errorf("watchpoint limit reached (max %d)", maxHW) }
drs.SetBreakpoint(uint8(idx), addr, false, true, 8)
Defensive patterns

Strategy: validation

Validate before calling

const maxHWBreakpoints = 4
if idx >= maxHWBreakpoints {
    return fmt.Errorf("hardware breakpoint limit is %d, cannot set index %d", maxHWBreakpoints, idx)
}

Try / catch

if err := drs.SetBreakpoint(idx, addr, read, write, sz); err != nil {
    if err.Error() == "hardware breakpoints exhausted" {
        // fall back to software breakpoint
    }
}

Prevention

When it happens

Trigger: Calling SetBreakpoint (directly or via proc's hardware breakpoint support) with idx >= len(drs.pAddrs), e.g. setting a 5th watchpoint/hardware breakpoint on a single thread while the previous four are still armed.

Common situations: Setting more than 4 simultaneous watchpoints in a debug session; watchpoints leaked across threads/iterations because they were never cleared; users expecting unlimited watchpoints like software breakpoints.

Related errors


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