go-delve/delve · warning

thread stack trace returned error

Error message

thread stack trace returned error

What it means

Error produced inside the dynamic-call breakpoint callback installed by traverse. When a runtime breakpoint fires on an unresolved call instruction, the callback takes a full thread stack trace (proc.ThreadStacktrace up to followCalls+2 frames) to locate the root function and compute dynamic call depth; if that stack walk fails, this error is returned and the dynamic call cannot be resolved.

Source

Thrown at service/debugger/debugger.go:1472

		if err != nil {
			return nil, fmt.Errorf("disassemble failed with error %w", err)
		}
		for _, instr := range text {
			// Dynamic functions need to be handled specially as their destination location
			// is not known statically, hence its required to put a breakpoint in order to
			// acquire the address of the function at runtime and we do this via a
			// call back mechanism
			if instr.IsCall() && instr.DestLoc == nil {
				dynbp, err := t.SetBreakpoint(0, instr.Loc.PC, proc.NextBreakpoint, nil)
				if err != nil {
					return nil, fmt.Errorf("error setting breakpoint inside deferreturn")
				}
				dynCallback := func(th proc.Thread, tgt *proc.Target) (bool, error) {
					// TODO(optimization): Consider using an iterator to avoid materializing
					// the full stack when we only need frames up to the root function
					rawlocs, err := proc.ThreadStacktrace(tgt, tgt.CurrentThread(), followCalls+2)
					if err != nil {
						return false, fmt.Errorf("thread stack trace returned error")
					}
					// Since the dynamic function is known only at runtime, the depth is likewise
					// calculated by referring to the stack and the mechanism is similar to that
					// used in pkg/terminal/command.go:printTraceOutput
					rootindex := -1
					for i := len(rawlocs) - 1; i >= 0; i-- {
						if rawlocs[i].Call.Fn.Name == rootstr {
							if rootindex == -1 {
								rootindex = i
								break
							}
						}
					}
					sdepth := rootindex + 1

					if sdepth+1 > followCalls {
						return false, nil
					}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Treat as transient: re-run the trace/continue — the callback failure aborts only that dynamic-call resolution.
  2. Reduce followCalls depth so fewer dynamic callbacks are armed and stacks are walked shallower.
  3. Ensure the target process is alive and not racing to exit around the traced call (add a sync point/breakpoint after the call).
  4. Check the binary has unwind information (DWARF/frame pointers) for the frames being traced.
  5. Update Delve; the follow-calls dynamic resolution code is under active development.

Example fix

// before
funcs, err := client.Functions("main", 8) // deep dynamic tracing, races with goroutine exit
// after
funcs, err := client.Functions("main", 3) // shallower walk, fewer runtime callbacks
Defensive patterns

Strategy: retry

Validate before calling

// confirm the target and goroutines are still live before tracing
state, err := client.GetState()
if err == nil && state.Exited {
    return fmt.Errorf("process exited; cannot trace dynamic calls")
}

Try / catch

for attempt := 0; attempt < 2; attempt++ {
    _, err = client.Functions(filter, followCalls)
    if err == nil || !strings.Contains(err.Error(), "thread stack trace returned error") {
        break
    }
    time.Sleep(100 * time.Millisecond) // transient unwind race; retry once
}

Prevention

When it happens

Trigger: During a continue/trace session with follow-calls enabled: the breakpoint callback fires on a dynamic call site and ThreadStacktrace fails because the goroutine's stack is unreadable or inconsistent — goroutine exiting between breakpoint hit and callback, corrupted stack unwinding info, extremely shallow stack, or the thread died / process resumed unexpectedly.

Common situations: Tracing deferreturn-driven calls where the goroutine unwinds quickly; race between process exit and callback execution; cgo or assembly frames that cannot be unwound; core-dump or remote targets where stack reads fail.

Related errors


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