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

  1. Update Delve — recent versions register fork/exec children with the TargetGroup before continuing, closing this race
  2. Avoid combining follow-exec/follow-fork with rapid attach/detach of child processes in the same session
  3. Check for the target process exiting concurrently (check /proc or process exit) so the thread no longer belongs to any known target
  4. 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

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.