go-delve/delve · error
could not read coroutine: %v
Error message
could not read coroutine: %v
What it means
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.
Source
Thrown at pkg/proc/target_exec.go:1783
if err != nil {
return false, fmt.Errorf("could not get registers trying to step into coroutine: %v", err)
}
dregs := bi.Arch.RegistersToDwarfRegisters(0, regs)
cst := text[0].DestLoc.Fn.extra(bi).closureStructType
clos := newVariable("", dregs.Uint64Val(bi.Arch.ContextRegNum), cst, p.BinInfo(), p.Memory())
// Get variable 'c' from the current closure, change its type to
// runtime.coro (it is normally iter.coro, which is an internal
// placeholder).
cvar, err := clos.structField("c")
if err != nil {
logflags.DebuggerLogger().Errorf("iter.Pull problems accessing captured 'c' variable in closure: %v", err)
return false, nil
}
cvar = cvar.maybeDereference()
if cvar.Unreadable != nil {
return false, fmt.Errorf("could not read coroutine: %v", cvar.Unreadable)
}
typRuntimeCoro, err := bi.findType("runtime.coro")
if err != nil {
logflags.DebuggerLogger().Errorf("could not find runtime.coro type: %v", err)
return false, nil
}
cvar = newVariable("", cvar.Addr, typRuntimeCoro, p.BinInfo(), p.Memory())
// Set a breakpoint on the first user frame of goroutine c.gp (but
// something special needs to happen if c.gp is executing
// runtime.corostart).
gp := cvar.loadFieldNamed("gp")
if gp == nil {
logflags.DebuggerLogger().Errorf("could not load runtime.coro.gp field (unreadable: %v)", cvar.Unreadable)
return false, nil
}
gaddr, _ := constant.Uint64Val(gp.Value)View on GitHub (pinned to a23773e6c3)
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
Example fix
// before: stepping into iter.Pull callback in an optimized binary // go build -o app . // optimizations -> cvar unreadable // after: disable optimizations for debuggable closures // go build -gcflags="all=-N -l" -o app .
Defensive patterns
Strategy: validation
Validate before calling
// before stepping into iterator callbacks, verify build flags and versions
// Go >= 1.23 required for runtime.coro
if !strings.HasPrefix(runtime.Version(), "go1.23") &&
!strings.HasPrefix(runtime.Version(), "go1.2") {
log.Fatal("coroutine stepping requires Go 1.23+")
}
// build with: go build -gcflags="all=-N -l" ... Try / catch
err := doStepInto()
if err != nil && strings.Contains(err.Error(), "could not read coroutine") {
// fall back to instruction-level stepping
return doStepInstruction()
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- could not get registers trying to step into coroutine: %v
- ErrMemoryReadUnavailable
- short read
- short read
- next while nexting
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/f37531400630feb7.
Report an issue: GitHub.