{"record":{"id":"251e717d713d5b55","repo":"go-delve/delve","slug":"could-not-find-thread-s","errorCode":null,"errorMessage":"could not find thread %s","messagePattern":"could not find thread (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/gdbserial/gdbserver.go","lineNumber":951,"sourceCode":"\t}\n\n\tstopReason := proc.StopUnknown\n\tif atstart {\n\t\tstopReason = proc.StopLaunched\n\t}\n\n\tif p.BinInfo().GOOS == \"linux\" {\n\t\tif err := linutil.ElfUpdateSharedObjects(p); err != nil {\n\t\t\treturn nil, stopReason, err\n\t\t}\n\t}\n\n\tif err := p.setCurrentBreakpoints(); err != nil {\n\t\treturn nil, stopReason, err\n\t}\n\n\tif trapthread == nil {\n\t\treturn nil, stopReason, fmt.Errorf(\"could not find thread %s\", threadID)\n\t}\n\n\terr := machTargetExcToError(trapthread.sig)\n\tif err != nil {\n\t\t// the signals that are reported here can not be propagated back to the target process.\n\t\ttrapthread.sig = 0\n\t}\n\tp.currentThread = trapthread\n\treturn trapthread, stopReason, err\n}\n\nfunc (p *gdbProcess) findThreadByStrID(threadID string) *gdbThread {\n\tfor _, thread := range p.threads {\n\t\tif thread.strID == threadID {\n\t\t\treturn thread\n\t\t}\n\t}\n\treturn nil","sourceCodeStart":933,"sourceCodeEnd":969,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/gdbserial/gdbserver.go#L933-L969","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// no pre-call validation possible; thread state changes asynchronously on the stub\ncanRetry := func(err error) bool { return strings.Contains(err.Error(), \"could not find thread \") }","typeGuard":null,"tryCatchPattern":"thread, reason, err := proc.WaitForStop(g)\nif err != nil && strings.HasPrefix(err.Error(), \"could not find thread \") {\n    thread, reason, err = proc.WaitForStop(g) // one retry: transient thread race\n}","preventionTips":["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"],"tags":["gdbserial","thread","stop-reply","race"],"backgroundTag":"thread-not-found","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}