go-delve/delve · error
could not find thread %s
Error message
could not find thread %s
What it means
After resuming and waiting for a stop, Delve looks up the thread ID reported by the stub (from the stop packet) in its local thread list via findThreadByStrID. If the stop packet names a thread that was never seen in qThreadStopInfo/jstopInfo or thread list updates, the trap thread is nil and this error is thrown.
Source
Thrown at pkg/proc/gdbserial/gdbserver.go:951
}
stopReason := proc.StopUnknown
if atstart {
stopReason = proc.StopLaunched
}
if p.BinInfo().GOOS == "linux" {
if err := linutil.ElfUpdateSharedObjects(p); err != nil {
return nil, stopReason, err
}
}
if err := p.setCurrentBreakpoints(); err != nil {
return nil, stopReason, err
}
if trapthread == nil {
return nil, stopReason, fmt.Errorf("could not find thread %s", threadID)
}
err := machTargetExcToError(trapthread.sig)
if err != nil {
// the signals that are reported here can not be propagated back to the target process.
trapthread.sig = 0
}
p.currentThread = trapthread
return trapthread, stopReason, err
}
func (p *gdbProcess) findThreadByStrID(threadID string) *gdbThread {
for _, thread := range p.threads {
if thread.strID == threadID {
return thread
}
}
return nilView on GitHub (pinned to a23773e6c3)
Solutions
- Retry the continue/step operation — the race often does not recur
- Update Delve and the remote stub to versions with consistent thread-stop handling
- Capture a log (dlv --log --log-output=rpc,gdbserial) of the stop packets to identify the bogus thread ID and report to the stub vendor
- If debugging rr traces, re-record the trace; checkpoint/replay ordering can change which thread reports the stop
Defensive patterns
Strategy: retry
Validate before calling
// no pre-call validation possible; thread state changes asynchronously on the stub
canRetry := func(err error) bool { return strings.Contains(err.Error(), "could not find thread ") } Try / catch
thread, reason, err := proc.WaitForStop(g)
if err != nil && strings.HasPrefix(err.Error(), "could not find thread ") {
thread, reason, err = proc.WaitForStop(g) // one retry: transient thread race
} Prevention
- Avoid clearing/manipulating threads concurrently with continue/step
- Keep stub and Delve versions current — thread stop-report races are actively fixed
- Enable gdbserial logging to correlate bogus thread IDs with stub packets
- Minimize thread churn (creation/exit) while the debugger controls execution
When it happens
Trigger: The stub's stop reply references thread ID X, but updateThreadList/handleThreadSignals never produced a gdbThread with strID X — e.g. the thread exited during the race between resume and stop, or qThreadStopInfo QListThreadsInStopReply data disagrees with the stop packet.
Common situations: Racing thread creation/exit in highly multithreaded inferiors; buggy stubs that report stale or bogus thread IDs in stop packets; rr or debugserver replay quirks where the trapping thread was torn down.
Related errors
- threadUpdater: Add after Finish
- direction change with internal breakpoints
- can not start a call injection while running backwards
- could not connect
- follow exec not supported
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/251e717d713d5b55.
Report an issue: GitHub.