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
- Retry the operation; thread churn races are often transient.
- Confirm the target is still running and the correct pid/task was used.
- Check macOS debugging entitlements/signing (get-task-allow, SIP) if failures are persistent.
- 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
- Retry transient thread-list failures; thread churn races are common.
- Confirm the target is quiescent (not rapidly spawning/exiting threads) at attach time.
- Check macOS SIP/entitlement settings for debugging permission.
- Test on the exact macOS version in CI; mach behavior varies by release.
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.