go-delve/delve · error

call is only supported with topmost stack frame

Error message

call is only supported with topmost stack frame

What it means

The DAP server's injected function-call (call) evaluation only supports expressions evaluated in the topmost stack frame. If the frameId refers to a parent frame (frame > 0), it returns this error, because variables of parent frames would silently be evaluated in the wrong (topmost) context, producing misleading results.

Source

Thrown at service/dap/server.go:3374

		// these contexts are used to copy the value.
		if ctxt == "clipboard" || ctxt == "variables" {
			opts |= showFullValue
		}
		exprVal, exprRef := s.convertVariableWithOpts(exprVar, fmt.Sprintf("(%s)", request.Arguments.Expression), opts, goid, frame)
		response.Body = dap.EvaluateResponseBody{Result: exprVal, Type: s.getTypeIfSupported(exprVar), VariablesReference: exprRef, IndexedVariables: getIndexedVariableCount(exprVar), NamedVariables: getNamedVariableCount(exprVar)}
	}
	s.send(response)
}

func (s *Session) doCall(goid, frame int, expr string) (*api.DebuggerState, []*proc.Variable, error) {
	// This call might be evaluated in the context of the frame that is not topmost
	// if the editor is set to view the variables for one of the parent frames.
	// If the call expression refers to any of these variables, unlike regular
	// expressions, it will evaluate them in the context of the topmost frame,
	// and the user will get an unexpected result or an unexpected symbol error.
	// We prevent this but disallowing any frames other than topmost.
	if frame > 0 {
		return nil, nil, errors.New("call is only supported with topmost stack frame")
	}
	stateBeforeCall, err := s.debugger.State( /*nowait*/ true)
	if err != nil {
		return nil, nil, err
	}
	// The return values of injected function calls are volatile.
	// Load as much useful data as possible.
	// TODO: investigate whether we need to increase other limits. For example,
	// the return value is a pointer to a temporary object, which can become
	// invalid by other injected function calls. Do we care about such use cases?
	loadCfg := s.loadConfig()
	loadCfg.MaxStringLen = maxStringLenInCallRetVars

	// TODO(polina): since call will resume execution of all goroutines,
	// we should do this asynchronously and send a continued event to the
	// editor, followed by a stop event when the call completes.
	state, err := s.debugger.Command(&api.DebuggerCommand{
		Name:                 api.Call,

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Select the topmost (innermost) stack frame before issuing the call expression
  2. Evaluate the call after stepping until the relevant frame is topmost
  3. Rewrite the expression to only use variables accessible from the topmost frame, or evaluate plain (non-call) expressions which work on any frame
  4. If the call must run in an outer context, stop at a breakpoint located in that frame instead

Example fix

// before: evaluate with frameId of frame 2
{expression: 'helper(x)', frameId: parentFrameId}
// after: use topmost frame or a non-call expression
{expression: 'helper(x)', frameId: topFrameId}
{expression: 'x', frameId: parentFrameId} // plain reads are allowed on any frame
Defensive patterns

Strategy: validation

Validate before calling

// only send call expressions when the selected frame is the topmost
if selectedFrameIndex != 0 && isLikelyCall(expr) {
    return errors.New("select the topmost frame to evaluate calls")
}

Try / catch

if err.Error() == "call is only supported with topmost stack frame" {
    // re-issue the evaluation with the topmost frameId
}

Prevention

When it happens

Trigger: Invoking a function call from a Watch/REPL/evaluate request while a non-topmost frame is selected (stackFramesId pointing to frame index > 0); drag-and-drop of a call expression onto a parent frame in the Variables view.

Common situations: Developers stopped deep in a call stack selecting an outer frame and typing a function call into the debug console; IDE watch expressions that reference a call while an ancestor frame is active.

Related errors


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