go-delve/delve · error
unknown goroutine %d
Error message
unknown goroutine %d
What it means
FindGoroutine resolves a goroutine ID to a *G using the partial and full goroutine caches plus runtime scans. Goroutine ID 0 is special: it is never a valid user goroutine, so requesting it explicitly (while not falling into the 'return selected' case) yields this error. The caller passed a goroutine identifier the debugger cannot resolve.
Source
Thrown at pkg/proc/variables.go:413
// to avoid reading any other goroutine and, more importantly, (b) we
// could be reading an incorrect value for the goroutine ID of a thread.
// This condition usually happens when a goroutine calls runtime.clone
// and for a short period of time two threads will appear to be running
// the same goroutine.
// 3. if the caller asks for gid == 0 and the selected goroutine is
// either 0 or nil.
// Goroutine 0 is special, it either means we have no current goroutine
// (for example, running C code), or that we are running on a special
// stack (system stack, signal handling stack) and we didn't properly
// detect it.
// Since there could be multiple goroutines '0' running simultaneously
// if the user requests it return the one that's already selected or
// nil if there isn't a selected goroutine.
return selg, nil
}
if gid == 0 {
return nil, fmt.Errorf("unknown goroutine %d", gid)
}
if g := dbp.gcache.partialGCache[gid]; g != nil {
return g, nil
}
// Calling GoroutinesInfo could be slow if there are many goroutines
// running, check if a running goroutine has been requested first.
for _, thread := range dbp.ThreadList() {
g, _ := GetG(thread)
if g != nil && g.ID == gid {
return g, nil
}
}
const goroutinesInfoLimit = 10
nextg := 0
for nextg >= 0 {View on GitHub (pinned to a23773e6c3)
Solutions
- Pass the actual target goroutine ID (positive integer) obtained from State()/ListGoroutines.
- Use GoroutineID = -1 (meaning 'use current/selected goroutine') instead of 0 for the non-specific case.
- Verify the goroutine still exists; re-fetch the goroutine list since IDs become invalid after exit.
Example fix
// before scope, err := debugger.ConvertEvalScope(target, 0, frame, 0) // after gid := -1 // or a real goroutine ID from state.CurrentThread goroutine scope, err := debugger.ConvertEvalScope(target, gid, frame, 0)
Defensive patterns
Strategy: validation
Validate before calling
if gid == 0 {
gid = -1 // sentinel: use currently selected goroutine
}
if gid > 0 {
found := false
for _, g := range goroutineList { if g.ID == gid { found = true; break } }
if !found { return fmt.Errorf("goroutine %d not in current list", gid) }
} Try / catch
scope, err := client.ConvertEvalScope(pid, gid, frame, 0)
if err != nil && strings.Contains(err.Error(), "unknown goroutine") {
state, _ := client.GetState()
gid = state.SelectedGoroutine.ID
scope, err = client.ConvertEvalScope(pid, gid, frame, 0)
} Prevention
- Never pass 0 as a goroutine ID; use -1 for 'current'
- Fetch goroutine IDs from ListGoroutines/GetState, never hard-code
- Validate IDs against a freshly fetched goroutine list
When it happens
Trigger: Calling debugger.ConvertEvalScope (or any API that reaches proc.FindGoroutine) with gid == 0, e.g. an RPC EvalScope/Command with GoroutineID=0 on a target whose API contract expects a positive goroutine ID.
Common situations: IDE/DAP clients sending GoroutineID 0 for 'current goroutine' when the server-side convention instead expects -1 (any) or the actual selected ID; scripts that default an unset variable to 0.
Related errors
- error derefing *G %s
- wrong type for pcs item %d: %v
- could not decode first frame
- unable to find function context
- unable to find locals: no debug information present in binar
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/e630bf9e0bead00e.
Report an issue: GitHub.