go-delve/delve · error

can not disable watchpoints

Error message

can not disable watchpoints

What it means

Watchpoints (data breakpoints on memory addresses/variables) cannot be toggled into the disabled state in Delve; they can only be created or removed. amendBreakpoint rejects any amend request that sets Disabled=true on a logical breakpoint that is a watchpoint.

Source

Thrown at service/debugger/debugger.go:868

	d.targetMutex.Lock()
	defer d.targetMutex.Unlock()
	if len(d.target.Targets()) != 1 {
		return ErrNotImplementedWithMultitarget
	}
	p := d.target.Selected
	return p.SetEBPFTracepoint(fnName)
}

// amendBreakpoint will update the breakpoint with the matching ID.
// It also enables or disables the breakpoint.
// We can consume this function to avoid locking a goroutine.
func (d *Debugger) amendBreakpoint(amend *api.Breakpoint) error {
	original := d.target.LogicalBreakpoints[amend.ID]
	if original == nil {
		return fmt.Errorf("no breakpoint with ID %d", amend.ID)
	}
	if d.isWatchpoint(original) && amend.Disabled {
		return errors.New("can not disable watchpoints")
	}
	err := d.copyLogicalBreakpointInfo(original, amend)
	if err != nil {
		return err
	}
	err = d.target.SetBreakpointEnabled(original, !amend.Disabled)
	if err != nil {
		return err
	}

	return nil
}

func (d *Debugger) isWatchpoint(lbp *proc.LogicalBreakpoint) bool {
	t := proc.ValidTargets{Group: d.target}
	for t.Next() {
		for _, bp := range t.Breakpoints().M {
			if bp.LogicalID() == lbp.LogicalID {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Clear the watchpoint instead of disabling it (ClearBreakpoint with its ID)
  2. Filter watchpoints out before sending batch disable operations from your frontend
  3. Re-create the watchpoint later when you want it inactive temporarily

Example fix

// before
amend := &api.Breakpoint{ID: watchpointID, Disabled: true}
d.AmendBreakpoint(amend) // error
// after
d.ClearBreakpoint(watchpointID) // remove; recreate when needed
Defensive patterns

Strategy: validation

Validate before calling

for _, bp := range toDisable {
    if isWatchpoint(bp) { // e.g. identified via WatchExpr != "" or Addr != 0 && Line == 0
        clearIDs = append(clearIDs, bp.ID)
    } else {
        amendIDs = append(amendIDs, bp.ID)
    }
}

Type guard

func isWatchpointBP(bp *api.Breakpoint) bool {
    return bp.WatchExpr != "" || bp.Addr != 0 && bp.Line == 0
}

Try / catch

err := dbg.AmendBreakpoint(&api.Breakpoint{ID: id, Disabled: true})
if err != nil && strings.Contains(err.Error(), "can not disable watchpoints") {
    dbg.ClearBreakpoint(id) // remove instead of disable
}

Prevention

When it happens

Trigger: Calling Debugger.AmendBreakpoint (RPC2 service/amendBreakpoint, DAP update of breakpoints, or terminal `toggle` on a watchpoint) with amend.Disabled == true where d.isWatchpoint(original) is true.

Common situations: IDEs that blanket-apply `disabled: true` to all breakpoints when the user disables a group; scripting tools toggling watchpoints like normal line breakpoints; stale UI state re-sending watchpoint configs after the watchpoint was conceptually removed.

Related errors


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