{"record":{"id":"90e08b6b813c8287","repo":"go-delve/delve","slug":"nil-goroutine-when-attempting-to-switch-to-gorouti","errorCode":null,"errorMessage":"nil goroutine when attempting to switch to goroutine stack","messagePattern":"nil goroutine when attempting to switch to goroutine stack","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/stack.go","lineNumber":346,"sourceCode":"\t\t\treturn true\n\t\t}\n\t}\n\n\tif it.frame.Ret <= 0 {\n\t\tit.atend = true\n\t\treturn true\n\t}\n\n\tit.sigret = it.frame.Current.Fn != nil && it.frame.Current.Fn.Name == \"runtime.sigpanic\"\n\tit.top = false\n\tit.pc = it.frame.Ret\n\tit.regs = callFrameRegs\n\treturn true\n}\n\nfunc (it *stackIterator) switchToGoroutineStack() error {\n\tif it.g == nil {\n\t\treturn fmt.Errorf(\"nil goroutine when attempting to switch to goroutine stack\")\n\t}\n\tit.systemstack = false\n\tit.top = false\n\tit.pc = it.g.PC\n\tit.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g.SP\n\tit.regs.AddReg(it.regs.BPRegNum, op.DwarfRegisterFromUint64(it.g.BP))\n\tif it.bi.Arch.usesLR {\n\t\tlrReg := it.regs.Reg(it.regs.LRRegNum)\n\t\tif lrReg == nil {\n\t\t\treturn fmt.Errorf(\"LR register is nil during stack switch\")\n\t\t}\n\t\tlrReg.Uint64Val = it.g.LR\n\t}\n\treturn nil\n}\n\n// Frame returns the frame the iterator is pointing at.\nfunc (it *stackIterator) Frame() Stackframe {","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/stack.go#L328-L364","documentation":"During stack unwinding, when the iterator crosses from the system stack (e.g. runtime code) back to the goroutine's own stack, it needs the goroutine descriptor (it.g) to restore PC/SP/BP. If it.g is nil the switch cannot be performed, so the iterator fails with this error. This is an internal invariant violation of the stack iterator.","triggerScenarios":"Iterating a stack where a systemstack frame is encountered (systemstack==true) but the stackIterator was created without a valid *g pointer — e.g. unwinding a thread whose current goroutine could not be resolved, or corrupted goroutine state.","commonSituations":"Inspecting a thread stopped in runtime/scheduler code where goroutine association failed; debugging core dumps or partially-corrupted memory; stale goroutine pointer after process state changed unexpectedly.","solutions":["Ensure you evaluate stacks via a goroutine (GoroutineScope) rather than a raw thread when in runtime frames","Re-read thread/goroutine state (Context, GetG) after the process resumes/stops again","Update Delve; this is often an internal bug triggered by runtime version changes","Check the target's Go runtime state isn't corrupted (e.g. from memory-write side effects)"],"exampleFix":"null","handlingStrategy":"type-guard","validationCode":"if it.g == nil { return fmt.Errorf(\"cannot unwind: goroutine unknown; use GoroutineScope\") }","typeGuard":"func canSwitchToGoroutineStack(it *stackIterator) bool { return it.g != nil }","tryCatchPattern":"err := iterateStack(g); if err != nil && strings.Contains(err.Error(), \"nil goroutine\") { /* fall back to thread-level stack or re-acquire g */ }","preventionTips":["Unwind stacks via goroutine scopes, not raw threads, when in runtime frames","Re-fetch goroutine state after every stop event","Avoid debugging processes with corrupted runtime memory","Update Delve when the Go runtime version changes"],"tags":["go","stack","goroutine","runtime"],"backgroundTag":"nil-goroutine-stack-switch","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}