{"record":{"id":"f37531400630feb7","repo":"go-delve/delve","slug":"could-not-read-coroutine-v","errorCode":null,"errorMessage":"could not read coroutine: %v","messagePattern":"could not read coroutine: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/target_exec.go","lineNumber":1783,"sourceCode":"\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}\n\ttypRuntimeCoro, err := bi.findType(\"runtime.coro\")\n\tif err != nil {\n\t\tlogflags.DebuggerLogger().Errorf(\"could not find runtime.coro type: %v\", err)\n\t\treturn false, nil\n\t}\n\tcvar = newVariable(\"\", cvar.Addr, typRuntimeCoro, p.BinInfo(), p.Memory())\n\n\t// Set a breakpoint on the first user frame of goroutine c.gp (but\n\t// something special needs to happen if c.gp is executing\n\t// runtime.corostart).\n\n\tgp := cvar.loadFieldNamed(\"gp\")\n\tif gp == nil {\n\t\tlogflags.DebuggerLogger().Errorf(\"could not load runtime.coro.gp field (unreadable: %v)\", cvar.Unreadable)\n\t\treturn false, nil\n\t}\n\tgaddr, _ := constant.Uint64Val(gp.Value)","sourceCodeStart":1765,"sourceCodeEnd":1801,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/target_exec.go#L1765-L1801","documentation":"When stepping into a Go coroutine callback (iter.Pull / range-over-func), Delve reads the captured 'c' variable (the runtime.coro) from the closure. If the resulting variable is marked Unreadable — its memory could not be read from the target — stepping into the coroutine fails with this error.","triggerScenarios":"stepIntoCoroutineMaybe dereferences the closure's captured variable 'c' and finds cvar.Unreadable != nil — the closure pointer was stale/zero, or the coroutine struct memory at the computed address is not readable in the target process.","commonSituations":"Stepping into iterator functions compiled with mismatched Go version vs Delve's expected runtime.coro layout; optimized builds where the closure capture was registerized/eliminated so the address is garbage; corrupted stack or wrong Context register value.","solutions":["Build the traced program without optimizations (-gcflags=\"all=-N -l\") so the closure capture 'c' is materialized in memory","Use a Go version and Delve version pair that both support coroutines (Go 1.23+ runtime.coro) — mismatched layouts make the read address invalid","Update Delve to pick up fixes in closure/variable reading for coroutine stepping","If the error is transient, retry the step; if persistent, step at the assembly level (step-instruction) instead"],"exampleFix":"// before: stepping into iter.Pull callback in an optimized binary\n//   go build -o app .   // optimizations -> cvar unreadable\n// after: disable optimizations for debuggable closures\n//   go build -gcflags=\"all=-N -l\" -o app .","handlingStrategy":"validation","validationCode":"// before stepping into iterator callbacks, verify build flags and versions\n// Go >= 1.23 required for runtime.coro\nif !strings.HasPrefix(runtime.Version(), \"go1.23\") &&\n   !strings.HasPrefix(runtime.Version(), \"go1.2\") {\n    log.Fatal(\"coroutine stepping requires Go 1.23+\")\n}\n// build with: go build -gcflags=\"all=-N -l\" ...","typeGuard":null,"tryCatchPattern":"err := doStepInto()\nif err != nil && strings.Contains(err.Error(), \"could not read coroutine\") {\n    // fall back to instruction-level stepping\n    return doStepInstruction()\n}","preventionTips":["Build the debugged program with -gcflags=\"all=-N -l\" so closure captures stay in memory","Pair Go 1.23+ with a Delve version that understands runtime.coro","Avoid stepping into iterator closures in stripped/optimized binaries","Fall back to step-instruction when coroutine variable reads fail"],"tags":["coroutine","memory-read","stepping"],"backgroundTag":"coroutine-variable-unreadable","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}