go-delve/delve · error · couldNotGetThreadList

could not get thread list

Error message

could not get thread list

What it means

This sentinel error is returned when the Mach call to fetch the actual thread list (`get_threads`) does not return KERN_SUCCESS while syncing threads of a task on macOS. The thread count succeeded but listing thread ports failed. It propagates from updateThreadListForTask through Launch and updateThreadList.

Source

Thrown at pkg/proc/native/proc_darwin.go:224

	return
}

func (dbp *nativeProcess) requestManualStop() (err error) {
	var (
		task          = C.mach_port_t(dbp.os.task)
		thread        = C.mach_port_t(dbp.memthread.os.threadAct)
		exceptionPort = C.mach_port_t(dbp.os.exceptionPort)
	)
	dbp.os.halt = true
	kret := C.raise_exception(task, thread, exceptionPort, C.EXC_BREAKPOINT)
	if kret != C.KERN_SUCCESS {
		return fmt.Errorf("could not raise mach exception")
	}
	return nil
}

var couldNotGetThreadCount = errors.New("could not get thread count")
var couldNotGetThreadList = errors.New("could not get thread list")

func (dbp *nativeProcess) updateThreadList() error {
	return dbp.updateThreadListForTask(dbp.os.task)
}

func (dbp *nativeProcess) updateThreadListForTask(task C.task_t) error {
	var (
		err   error
		kret  C.kern_return_t
		count C.int
		list  []uint32
	)

	for {
		count = C.thread_count(task)
		if count == -1 {
			return couldNotGetThreadCount
		}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Retry the operation; thread churn races are often transient.
  2. Confirm the target is still running and the correct pid/task was used.
  3. Check macOS debugging entitlements/signing (get-task-allow, SIP) if failures are persistent.
  4. Upgrade to the latest delve, as Mach thread-list handling bugs have been fixed over time.
Defensive patterns

Strategy: retry

Validate before calling

// confirm the process exists before debugging
out, err := exec.Command("pgrep", "-q", name).Output()
if err != nil {
	return fmt.Errorf("process %s not found", name)
}

Type guard

func isCouldNotGetThreadList(err error) bool {
	return err != nil && err.Error() == "could not get thread list"
}

Try / catch

err := launchWithRetry(func() error {
	_, err := dlv.Launch(...)
	if err != nil && err.Error() == "could not get thread list" {
		return errRetryable
	}
	return err
})

Prevention

When it happens

Trigger: Launch or updateThreadList on macOS where C.get_threads(task, ...) returns a kern_return_t other than KERN_SUCCESS (including the retry sentinel -2 loop being exhausted or failing), typically due to an invalid/freed task port or a thread dying concurrently.

Common situations: Target process exits while delve refreshes thread state; attaching to a busy multi-threaded process where threads churn during enumeration; restricted task ports on newer macOS releases.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/9892d243d295cfd6. Report an issue: GitHub.