{"record":{"id":"9892d243d295cfd6","repo":"go-delve/delve","slug":"could-not-get-thread-list","errorCode":null,"errorMessage":"could not get thread list","messagePattern":"could not get thread list","errorType":"error_code","errorClass":"couldNotGetThreadList","httpStatus":null,"severity":"error","filePath":"pkg/proc/native/proc_darwin.go","lineNumber":224,"sourceCode":"\treturn\n}\n\nfunc (dbp *nativeProcess) requestManualStop() (err error) {\n\tvar (\n\t\ttask          = C.mach_port_t(dbp.os.task)\n\t\tthread        = C.mach_port_t(dbp.memthread.os.threadAct)\n\t\texceptionPort = C.mach_port_t(dbp.os.exceptionPort)\n\t)\n\tdbp.os.halt = true\n\tkret := C.raise_exception(task, thread, exceptionPort, C.EXC_BREAKPOINT)\n\tif kret != C.KERN_SUCCESS {\n\t\treturn fmt.Errorf(\"could not raise mach exception\")\n\t}\n\treturn nil\n}\n\nvar couldNotGetThreadCount = errors.New(\"could not get thread count\")\nvar couldNotGetThreadList = errors.New(\"could not get thread list\")\n\nfunc (dbp *nativeProcess) updateThreadList() error {\n\treturn dbp.updateThreadListForTask(dbp.os.task)\n}\n\nfunc (dbp *nativeProcess) updateThreadListForTask(task C.task_t) error {\n\tvar (\n\t\terr   error\n\t\tkret  C.kern_return_t\n\t\tcount C.int\n\t\tlist  []uint32\n\t)\n\n\tfor {\n\t\tcount = C.thread_count(task)\n\t\tif count == -1 {\n\t\t\treturn couldNotGetThreadCount\n\t\t}","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/native/proc_darwin.go#L206-L242","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// confirm the process exists before debugging\nout, err := exec.Command(\"pgrep\", \"-q\", name).Output()\nif err != nil {\n\treturn fmt.Errorf(\"process %s not found\", name)\n}","typeGuard":"func isCouldNotGetThreadList(err error) bool {\n\treturn err != nil && err.Error() == \"could not get thread list\"\n}","tryCatchPattern":"err := launchWithRetry(func() error {\n\t_, err := dlv.Launch(...)\n\tif err != nil && err.Error() == \"could not get thread list\" {\n\t\treturn errRetryable\n\t}\n\treturn err\n})","preventionTips":["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."],"tags":["macos","mach","debugging","threads"],"backgroundTag":"mach-thread-enumeration-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}