go-delve/delve · error
could not determine running goroutine for thread %#x current
Error message
could not determine running goroutine for thread %#x currently executing the function call injection protocol: %v
What it means
During the function call injection protocol Delve must know which goroutine is running on the thread that hit the injected-call breakpoint, because call-injection state is tracked per goroutine (t.fncallForG). findCallInjectionStateForThread calls GetG(thread) to recover the goroutine; if that fails (runtime structures unreadable, thread not executing Go code, goroutine exited), it throws this error wrapping the underlying GetG failure.
Source
Thrown at pkg/proc/fncall.go:1202
fncallLog("step for injection on goroutine %d (current) thread=%d (location %s)", g.ID, thread.ThreadID(), loc.Fn.Name)
t.currentThread = thread
callinj.evalStack.resume(g)
if !callinj.evalStack.callInjectionContinue {
err := finishEvalExpressionWithCalls(t, g, callinj.evalStack)
if err != nil {
return done, err
}
done = true
}
}
return done, nil
}
func findCallInjectionStateForThread(t *Target, thread Thread) (*G, *callInjection, error) {
g, err := GetG(thread)
if err != nil {
return nil, nil, fmt.Errorf("could not determine running goroutine for thread %#x currently executing the function call injection protocol: %v", thread.ThreadID(), err)
}
fncallLog("findCallInjectionStateForThread thread=%d goroutine=%d", thread.ThreadID(), g.ID)
notfound := func() error {
return fmt.Errorf("could not recover call injection state for goroutine %d (thread %d)", g.ID, thread.ThreadID())
}
callinj := t.fncallForG[g.ID]
if callinj != nil {
if callinj.evalStack == nil {
return nil, nil, notfound()
}
return g, callinj, nil
}
// In Go 1.15 and later the call injection protocol will switch to a
// different goroutine.
// Here we try to recover the injection goroutine by checking the injection
// thread.
View on GitHub (pinned to a23773e6c3)
Solutions
- Retry the call injection; transient scheduling races often resolve on a second attempt.
- Ensure the thread is executing Go code (not cgo/runtime) when the call completes; avoid injecting calls that can call into C.
- Verify the binary has full Go runtime symbol/DWARF information (don't strip; build with default flags).
- Update Delve; check github.com/go-delve/delve for known GetG/GetG issues with your Go version.
Defensive patterns
Strategy: try-catch
Try / catch
err := injectCall(g, fn)
if err != nil && strings.Contains(err.Error(), "could not determine running goroutine") {
// goroutine may have exited or thread left Go code; reschedule on a live goroutine
return retryOnLiveGoroutine(fn)
}
return err Prevention
- Don't inject calls that can run cgo or non-Go code
- Don't inject calls on goroutines about to exit
- Ensure binaries keep runtime symbols (no stripping)
- Retry transient failures once before giving up
When it happens
Trigger: GetG fails on a thread that is mid-call-injection — e.g. the goroutine executing the injected call has exited, the thread is running non-Go code (cgo or runtime), or the G struct cannot be read from process memory at the moment the breakpoint fires.
Common situations: Injected call triggers while the target goroutine has died or the thread left Go code; attaching to a process whose runtime state is unreadable; race where the runtime schedules the thread away between injection steps; debugging stripped binaries where runtime symbols are missing.
Related errors
- could not get panic: %v
- could not restore LR: %v
- could not set call receiver: %v
- function %s not found
- unexpected return type for mallocgc call: %v
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/a1a1ef64fb71fd52.
Report an issue: GitHub.