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
- Treat as transient: re-run the trace/continue — the callback failure aborts only that dynamic-call resolution.
- Reduce followCalls depth so fewer dynamic callbacks are armed and stacks are walked shallower.
- Ensure the target process is alive and not racing to exit around the traced call (add a sync point/breakpoint after the call).
- Check the binary has unwind information (DWARF/frame pointers) for the frames being traced.
- 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
- Retry once — stack unwinds often fail transiently while the goroutine is exiting.
- Reduce followCalls so fewer dynamic callbacks walk stacks.
- Add a sync point after traced calls so goroutines don't exit mid-trace.
- Ensure DWARF/frame-pointer unwind info exists in the binary.
- Avoid tracing goroutines that finish instantly (e.g. `go func(){...}()` one-shots).
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
- wrong type for pcs item %d: %v
- traverse failed with error %w
- disassemble failed with error %w
- registers inside callback returned err
- failed to disassemble instruction: %w
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/60a58754290f2cbc.
Report an issue: GitHub.