{"record":{"id":"9ebb1d33fa5ec1bf","repo":"go-delve/delve","slug":"could-not-get-registers-trying-to-step-into-corout","errorCode":null,"errorMessage":"could not get registers trying to step into coroutine: %v","messagePattern":"could not get registers trying to step into coroutine: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/target_exec.go","lineNumber":1766,"sourceCode":"\t}\n}\n\n// stepIntoCoroutineMaybe: if the current instruction is a call to a closure\n// defined into iter.Pull (i.e. next, yield and stop) stepIntoCoroutineMaybe\n// will set up a new breakpoint to step into the associated coroutine code\n// and returns true.\n// In every other case it returns false.\nfunc stepIntoCoroutineMaybe(curthread Thread, p *Target, text []AsmInstruction) (bool, error) {\n\tif len(text) == 0 || !text[0].IsCall() || text[0].DestLoc == nil || text[0].DestLoc.Fn == nil || !strings.HasPrefix(text[0].DestLoc.Fn.Name, \"iter.Pull\") || !strings.Contains(text[0].DestLoc.Fn.Name, \".func\") {\n\t\treturn false, nil\n\t}\n\tbi := p.BinInfo()\n\n\t// Read the closure that we are going to call currently\n\n\tregs, err := curthread.Registers()\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"could not get registers trying to step into coroutine: %v\", err)\n\t}\n\tdregs := bi.Arch.RegistersToDwarfRegisters(0, regs)\n\tcst := text[0].DestLoc.Fn.extra(bi).closureStructType\n\tclos := newVariable(\"\", dregs.Uint64Val(bi.Arch.ContextRegNum), cst, p.BinInfo(), p.Memory())\n\n\t// Get variable 'c' from the current closure, change its type to\n\t// runtime.coro (it is normally iter.coro, which is an internal\n\t// placeholder).\n\n\tcvar, err := clos.structField(\"c\")\n\tif err != nil {\n\t\tlogflags.DebuggerLogger().Errorf(\"iter.Pull problems accessing captured 'c' variable in closure: %v\", err)\n\t\treturn false, nil\n\t}\n\tcvar = cvar.maybeDereference()\n\tif cvar.Unreadable != nil {\n\t\treturn false, fmt.Errorf(\"could not read coroutine: %v\", cvar.Unreadable)\n\t}","sourceCodeStart":1748,"sourceCodeEnd":1784,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/target_exec.go#L1748-L1784","documentation":"Delve implements step-into for Go 1.23+ coroutine-style callbacks (iter.Pull / runtime.newcoro) by reading the closure that will be called. The first step requires the current thread's CPU registers; if Registers() fails (thread exited, process died, or ptrace error), stepping into the coroutine aborts with this wrapped error.","triggerScenarios":"Calling stepIntoCallback -> stepIntoCoroutineMaybe when curthread.Registers() returns an error — the thread stopped/exited between the step and the register read, or the OS backend failed to fetch registers.","commonSituations":"Stepping into iterator functions (range-over-func with iter.Pull) while the traced process is under heavy thread churn; attaching to a thread that dies mid-step; ptrace register access failures on some kernels/containers lacking permissions.","solutions":["Retry the step — transient thread-exit races usually resolve on the next step command","Verify ptrace permissions (kernel.yama.ptrace_scope, container CAP_SYS_PTRACE / --privileged) if registers are consistently unavailable","Ensure the process has not exited — check target liveness before stepping","Update Delve and Go: newer runtimes/backends handle coroutine closures and thread races more robustly"],"exampleFix":"// before: stepping while the target is racing to exit\n//   (dlv) step   // thread dies mid-step -> error\n// after: confirm the target is alive / retry\n//   (dlv) goroutines   // verify goroutine exists\n//   (dlv) step         // retry the step","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := doStep()\nif err != nil && strings.Contains(err.Error(), \"could not get registers\") {\n    // thread may have exited mid-step; verify target then retry\n    st, stateErr := client.GetState()\n    if stateErr == nil && !st.Exited {\n        err = doStep()\n    }\n    return err\n}","preventionTips":["Confirm ptrace permissions (yama.ptrace_scope, CAP_SYS_PTRACE) before debugging in containers","Check the process is still alive before stepping","Keep Go and Delve versions current for coroutine stepping support","Retry transient register-read failures once before surfacing them"],"tags":["stepping","registers","coroutine"],"backgroundTag":"register-read-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}