go-delve/delve · error

breakpoint already exists

Error message

breakpoint already exists

What it means

When handling setBreakpoints for named/function breakpoints that already exist, the session deduplicates by breakpoint name. If a requested breakpoint name is already present in createdBps (previously created in this same request cycle), it errors with 'breakpoint already exists' instead of creating a duplicate. This protects DAP clients from ambiguous duplicate breakpoint entries.

Source

Thrown at service/dap/server.go:1734

	// createdBps is a set of breakpoint names that have been added
	// during this request. This is used to catch duplicate set
	// breakpoints requests and to track which breakpoints need to
	// be deleted.
	createdBps := make(map[string]struct{}, len(existingBps))

	breakpoints := make([]dap.Breakpoint, totalBps)
	// Amend existing breakpoints.
	for i := range totalBps {
		want := metadataFunc(i)
		got, ok := existingBps[want.name]
		if got == nil || !ok {
			// Skip if the breakpoint does not already exist.
			continue
		}

		var err error
		if _, ok := createdBps[want.name]; ok {
			err = errors.New("breakpoint already exists")
		} else {
			got.Disabled = false
			got.Cond = want.condition
			got.HitCond = want.hitCondition
			err = setLogMessage(got, want.logMessage)
			if err == nil {
				err = s.debugger.AmendBreakpoint(got)
			}
		}
		createdBps[want.name] = struct{}{}
		s.updateBreakpointsResponse(breakpoints, i, err, got)
	}

	// Clear breakpoints.
	// Any breakpoint that existed before this request but was not amended must be deleted.
	s.clearBreakpoints(existingBps, createdBps)

	// Check if the plugin package is present or follow-exec is enabled.

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Deduplicate the requested breakpoint list on the client before sending setBreakpoints (set of names)
  2. Remove the conflicting breakpoint (via removeBreakpoint or clearing the list) before re-adding it
  3. Ensure one breakpoint kind per name: do not send both a function breakpoint and an equivalent file:line breakpoint with the same name
  4. Update the DAP client to replace breakpoints by name rather than append

Example fix

// before: duplicate names in request
breakpoints: [{name: 'main.foo:12'}, {name: 'main.foo:12'}]
// after: dedupe client-side
unique := map[string]bool{}
for _, bp := range reqs { if !unique[bp.name] { unique[bp.name] = true; out = append(out, bp) } }
Defensive patterns

Strategy: validation

Validate before calling

// dedupe requested breakpoints by name before setBreakpoints
seen := map[string]bool{}
for _, bp := range req.Breakpoints {
    if seen[bp.Name] { continue }
    seen[bp.Name] = true
    out = append(out, bp)
}

Try / catch

if err.Error() == "breakpoint already exists" {
    // remove the existing breakpoint, then re-issue the request once
}

Prevention

When it happens

Trigger: A setBreakpoints request whose list contains two entries resolving to the same breakpoint name (e.g. 'main.foo:12' twice); a second setBreakpoints request for the same function location while the previous one's breakpoints are being reused rather than cleared.

Common situations: Client UI sending both a function breakpoint and a file:line breakpoint that resolve to the same name; request lists built programmatically with duplicates; stale client state re-sending already-created breakpoints within one update batch.

Related errors


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