go-delve/delve · warning

call stopped

Error message

call stopped

What it means

After an injected function call is issued, if the target stops (a breakpoint is hit, signal arrives, etc.) before the call completes, the session sends a stopped event, resets handles, and returns the sentinel 'call stopped' instead of a result. The call was injected but its completion is interrupted; delve currently cannot resume and complete it transparently.

Source

Thrown at service/dap/server.go:3459

	// to reset all the handles (both variables and stack frames).
	//
	// We considered sending a stopped event after each call unconditionally, but a stopped
	// event can be expensive and can interact badly with the client-side optimization
	// to refresh information. For example, VS Code reissues scopes/evaluate (for watch) after
	// completing a setVariable or evaluate request for repl context. Thus, for now, we
	// do not trigger a stopped event and hope editors to refetch the updated state as soon
	// as the user resumes debugging.

	if !found || !isAssignment && retVars == nil {
		// The call got interrupted by a stop (e.g. breakpoint in injected
		// function call or in another goroutine).
		s.resetHandlesForStoppedEvent()
		s.sendStoppedEvent(state)

		// TODO(polina): once this is asynchronous, we could wait to reply until the user
		// continues, call ends, original stop point is hit and return values are available
		// instead of returning an error 'call stopped' here.
		return nil, nil, errors.New("call stopped")
	}
	return state, retVars, nil
}

func (s *Session) sendStoppedEvent(state *api.DebuggerState) {
	stopped := &dap.StoppedEvent{Event: *s.newEvent("stopped")}
	stopped.Body.AllThreadsStopped = true
	stopped.Body.ThreadId = int(stoppedGoroutineID(state))
	stopped.Body.Reason = s.debugger.StopReason().String()
	s.send(stopped)
}

// onTerminateRequest sends a not-yet-implemented error response.
// Capability 'supportsTerminateRequest' is not set in 'initialize' response.
func (s *Session) onTerminateRequest(request *dap.TerminateRequest) {
	s.sendNotYetImplementedErrorResponse(request.Request)
}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Disable or remove breakpoints along the called function's path before evaluating the call
  2. Retry the call after continuing; the call result is not available and the original stop point must be resumed
  3. Avoid evaluating functions that trigger signals or long pauses
  4. If a stop is needed, cancel the call workflow and set a proper breakpoint instead of injecting a call

Example fix

// before: evaluate call with a breakpoint inside callee
{expression: 'compute(x)'} // breakpoint in compute -> 'call stopped'
// after: clear the breakpoint first
deleteBreakpoint(computeLine)
{expression: 'compute(x)'}
Defensive patterns

Strategy: retry

Validate before calling

// remove breakpoints in the callee path before injecting the call
for _, bp := range breakpointsInFunc(calleeName) { removeBreakpoint(bp.ID) }

Try / catch

if err.Error() == "call stopped" {
    // a stop event already arrived; continue execution, wait for the original
    // stop point, then retry the call once breakpoints are cleared
}

Prevention

When it happens

Trigger: An injected call crosses a breakpoint that fires mid-call; a signal or manual pause lands while the call executes; stepping/other stop events occur during the injected call.

Common situations: Calling a function whose body contains breakpoints while evaluating from the console; hitting an async signal during a long-running injected call; user pressing pause during a slow call evaluation.

Related errors


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