{"record":{"id":"7585ba96057cad1c","repo":"go-delve/delve","slug":"could-not-raise-mach-exception","errorCode":null,"errorMessage":"could not raise mach exception","messagePattern":"could not raise mach exception","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/native/proc_darwin.go","lineNumber":218,"sourceCode":"\t\tport := C.mach_port_wait(dbp.os.portSet, &task, C.int(0))\n\t\tif port == dbp.os.notificationPort {\n\t\t\tbreak\n\t\t}\n\t}\n\tdbp.postExit()\n\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)","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/native/proc_darwin.go#L200-L236","documentation":"requestManualStop implements Delve's halt by sending a mach EXC_BREAKPOINT exception to the inferior's exception port via raise_exception. If the mach call fails (non-KERN_SUCCESS), the stop request cannot be delivered and the error \"could not raise mach exception\" is returned.","triggerScenarios":"Calling Stop/requestManualStop while the debuggee is running on macOS when raise_exception fails: the task or exception port is invalid (inferior exited or exec'd and the task port went stale), or the port rights were lost.","commonSituations":"User presses Ctrl-C / issues `halt` just as the inferior exits or calls execve, invalidating dbp.os.exceptionPort; mach port exhaustion; a prior attach that only partially succeeded leaving ports uninitialized.","solutions":["Retry the halt after checking the target state (`goroutines`, `continue`) — the process may have exited.","Verify the inferior didn't exec a new binary (task port changes across execve).","Restart the debug session if the exception port is stale; partial-attach states are not recoverable.","Report/reproduce with a minimal case if it happens during normal continue/halt, as it may be a backend bug."],"exampleFix":"// before\n(dlv) halt   // inferior already exited -> mach exception fails\n// after\n(dlv) goroutines   // confirm target still alive\n(dlv) halt","handlingStrategy":"try-catch","validationCode":"// Confirm the target still exists before requesting a halt:\nif !proc.Valid() {\n    return fmt.Errorf(\"target already exited; halt not possible\")\n}","typeGuard":null,"tryCatchPattern":"err := dbp.requestManualStop()\nif err != nil && strings.Contains(err.Error(), \"could not raise mach exception\") {\n    // target likely exited or exec'd; re-check target state instead of retrying blindly\n}","preventionTips":["Check target liveness before issuing halt.","Expect halts to fail across execve boundaries; stop before/after the exec.","Avoid racing halt with program exit in scripts/tests.","Keep the session single-debugger — no concurrent lldb/dlv on the same task."],"tags":["darwin","mach-exception","halt","stale-port"],"backgroundTag":"mach-exception-raise-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}