go-delve/delve · error
could not find target for thread %d
Error message
could not find target for thread %d
What it means
During Continue, after the underlying process group stops on a trap thread, Delve maps the OS thread ID back to the debugged Target (process) it belongs to. If no target in the TargetGroup owns that thread, Continue returns this error because the debugger cannot attribute the stop event to any process.
Source
Thrown at pkg/proc/target_exec.go:100
err := grp.manageUnsatisfiableBreakpoints()
if err != nil {
return err
}
if grp.cctx.CheckAndClearManualStopRequest() {
grp.finishManualStop()
return nil
}
for _, dbp := range grp.targets {
dbp.ClearCaches()
}
logflags.DebuggerLogger().Debugf("ContinueOnce")
trapthread, stopReason, contOnceErr := grp.procgrp.ContinueOnce(grp.cctx)
var traptgt *Target
if trapthread != nil {
traptgt = grp.TargetForThread(trapthread.ThreadID())
if traptgt == nil {
return fmt.Errorf("could not find target for thread %d", trapthread.ThreadID())
}
} else {
traptgt = grp.targets[0]
}
traptgt.StopReason = stopReason
it := ValidTargets{Group: grp}
for it.Next() {
// Both selectedGoroutine and current thread are stale here, since we can
// only set their definitive value *after* evaluating breakpoint
// conditions here we give them temporary non-stale values.
it.selectedGoroutine = nil
curthread := it.currentThread
for _, thread := range it.ThreadList() {
if thread.Breakpoint().Breakpoint != nil {
it.currentThread = thread
thread.Breakpoint().Breakpoint.checkCondition(it.Target, thread, thread.Breakpoint())
}View on GitHub (pinned to a23773e6c3)
Solutions
- Update Delve — recent versions register fork/exec children with the TargetGroup before continuing, closing this race
- Avoid combining follow-exec/follow-fork with rapid attach/detach of child processes in the same session
- Check for the target process exiting concurrently (check /proc or process exit) so the thread no longer belongs to any known target
- If reproducible, capture 'dlv --log' output and file an issue with the process/thread list at the time of the error
Defensive patterns
Strategy: retry
Try / catch
state, err := client.Continue()
if err != nil && strings.Contains(err.Error(), "could not find target for thread") {
// transient multiprocess race: re-fetch state or retry once
state, err = client.GetState()
if err != nil {
return fmt.Errorf("continue failed: %w", err)
}
} Prevention
- Keep Delve updated for follow-exec/fork registration fixes
- Avoid detaching child processes while continuing the parent in follow-fork sessions
- Use 'dlv --log' to capture thread/target state when the error reproduces
- Prefer current Go/Delve versions for multiprocess debugging
When it happens
Trigger: grp.Continue() (via ContinueOnce) returns a trapthread whose ThreadID is not present in any of grp.targets — e.g. a newly spawned/forked child process not yet registered, or a thread belonging to an exited/detached target.
Common situations: Multi-process debugging (follow-exec/follow-fork) where a child process appears before Delve registers it; attaching/detaching races during TestAttachDetach-style workflows; kernel/ptrace reporting a stop from a thread of a process Delve already removed.
Related errors
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/46cf3da341cec54b.
Report an issue: GitHub.