go-delve/delve · error

no breakpoint with ID %d

Error message

no breakpoint with ID %d

What it means

amendBreakpoint looks up d.target.LogicalBreakpoints[amend.ID]; if no logical breakpoint with that ID exists, it returns this error. AmendBreakpoint is used by clients to update (enable/disable, change condition, hitcount) an existing breakpoint, so it requires a previously created breakpoint ID.

Source

Thrown at service/debugger/debugger.go:865

}

func (d *Debugger) CreateEBPFTracepoint(fnName string) error {
	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}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. List current breakpoints (ListBreakpoints / `breakpoints` command) and use a valid ID.
  2. Create the breakpoint first via SetBreakpoint/ClearBreakpoint flow, then amend its returned ID.
  3. Re-sync client breakpoint state after restart; discarded breakpoints cannot be amended.
  4. Guard against amend.ID == 0 — delve-assigned IDs start at 1.

Example fix

// before
bp := &api.Breakpoint{ID: 42, Disabled: true}
d.AmendBreakpoint(bp)
// after
bps, _ := d.ListBreakpoints(false)
if len(bps) > 0 {
    bp := &api.Breakpoint{ID: bps[0].ID, Disabled: true}
    d.AmendBreakpoint(bp)
}
Defensive patterns

Strategy: validation

Validate before calling

bps, err := d.ListBreakpoints(false)
if err != nil {
    return err
}
known := map[int]bool{}
for _, bp := range bps {
    known[bp.ID] = true
}
if !known[amend.ID] {
    return fmt.Errorf("breakpoint %d not live; refresh state", amend.ID)
}

Try / catch

if err := d.AmendBreakpoint(bp); err != nil && strings.Contains(err.Error(), "no breakpoint with ID") {
    // refresh local breakpoint cache and re-resolve the ID
    bps, _ := d.ListBreakpoints(false)
    _ = bps
}

Prevention

When it happens

Trigger: Calling Debugger.AmendBreakpoint (or RPC2/DAP equivalent) with an api.Breakpoint whose ID was never assigned by delve, an ID from a previous session, ID 0, or an ID of a breakpoint already cleared.

Common situations: IDE state out of sync after a restart that discarded breakpoints; client caching stale breakpoint IDs across `clear` or restart; constructing a Breakpoint manually with a guessed ID; race where another client deleted the breakpoint.

Related errors


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