go-delve/delve · error
could not find watchpoint at address %#x
Error message
could not find watchpoint at address %#x
What it means
On macOS (debugserver/mach exceptions), the thread's watchAddr records the address the thread stopped at. SetCurrentBreakpoint tries to match it against known breakpoints; if it is not a known breakpoint, not a hardcoded breakpoint instruction, and not found in the breakpoint map, Delve reports it cannot resolve the watchpoint at that address.
Source
Thrown at pkg/proc/gdbserial/gdbserver.go:1986
// t.watchAddr on certain mach kernel versions could contain the address of a
// software breakpoint, hardcoded breakpoint (e.g. runtime.Breakpoint) or a
// hardware watchpoint. The mach exception produced by the kernel *should* disambiguate
// but it doesn't.
if t.watchAddr > 0 {
t.CurrentBreakpoint.Breakpoint = t.p.Breakpoints().M[t.watchAddr]
if t.CurrentBreakpoint.Breakpoint == nil {
buf := make([]byte, t.BinInfo().Arch.BreakpointSize())
_, err := t.p.ReadMemory(buf, t.watchAddr)
isHardcodedBreakpoint := err == nil && (bytes.Equal(t.BinInfo().Arch.BreakpointInstruction(), buf) || bytes.Equal(t.BinInfo().Arch.AltBreakpointInstruction(), buf))
if isHardcodedBreakpoint {
// This is a hardcoded breakpoint, ignore.
// TODO(deparker): There's an optimization here since we will do this
// again at a higher level to determine if we've stopped at a hardcoded breakpoint.
// We could set some state here so that we don't do extra work later.
t.watchAddr = 0
return nil
}
return fmt.Errorf("could not find watchpoint at address %#x", t.watchAddr)
}
return nil
}
if t.watchReg >= 0 {
for _, bp := range t.p.Breakpoints().M {
if bp.WatchType != 0 && bp.HWBreakIndex == uint8(t.watchReg) {
t.CurrentBreakpoint.Breakpoint = bp
return nil
}
}
}
regs, err := t.Registers()
if err != nil {
return err
}
pc := regs.PC()
if bp, ok := t.p.FindBreakpoint(pc); ok {
if t.regs.PC() != bp.Addr {View on GitHub (pinned to a23773e6c3)
Solutions
- Retry the continue; if the breakpoint was cleared concurrently the race typically resolves
- Check that no other tool is injecting breakpoint instructions into the target
- Update Delve — mach exception watchAddr disambiguation has known fixes on newer macOS versions
- If reproducible, capture Delve logs with the watchAddr value and inspect what instruction sits at that address in the target
Defensive patterns
Strategy: try-catch
Validate before calling
// no caller-side pre-check possible; error arises from mach exception disambiguation
isWatchpointErr := func(err error) bool {
return strings.Contains(err.Error(), "could not find watchpoint at address")
} Try / catch
err := thread.SetCurrentBreakpoint(false)
if isWatchpointErr(err) {
// race or foreign trap; re-continue and re-evaluate on next stop
_ = proc.Continue()
} Prevention
- Do not clear breakpoints while target threads may be hitting them
- Avoid running other debuggers/instrumentation that inject traps into the same process
- Keep Delve and macOS updated — mach exception handling fixes land regularly
- Investigate any reproducible address: read memory there to see what instruction triggered it
When it happens
Trigger: A mach exception reports a stop whose address is neither a Delve-registered breakpoint/watchpoint nor a Go hardcoded breakpoint (runtime.Breakpoint) — e.g. a breakpoint cleared between the stop and SetCurrentBreakpoint, or a foreign/trap instruction injected by something else.
Common situations: Clearing breakpoints while threads are concurrently hitting them on macOS; mixing Delve with another debugger/instrumentation injecting INT3s; kernel/dispatch quirks where mach exceptions report software breakpoint addresses ambiguously.
Related errors
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/8cedca3e48d6c37a.
Report an issue: GitHub.