{"record":{"id":"04d6f083ae34d54f","repo":"go-delve/delve","slug":"could-not-get-panic-v","errorCode":null,"errorMessage":"could not get panic: %v","messagePattern":"could not get panic: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/fncall.go","lineNumber":954,"sourceCode":"\t\t\tfncall.addrsToPin = slices.Compact(fncall.addrsToPin)\n\n\t\t\treturn false // will continue with evalop.CallInjectionComplete2\n\t\t}\n\n\t\tcallInjectionComplete2(callScope, bi, fncall, regs, thread)\n\n\tcase debugCallRegReadPanic: // 2\n\t\t// read panic value from stack\n\t\tstack.callInjectionContinue = true\n\t\tarchoff := uint64(0)\n\t\tif bi.Arch.Name == \"arm64\" || bi.Arch.Name == \"loong64\" {\n\t\t\tarchoff = 8\n\t\t} else if bi.Arch.Name == \"ppc64le\" {\n\t\t\tarchoff = 32\n\t\t}\n\t\tfncall.panicvar, err = readStackVariable(p, thread, regs, archoff, \"interface {}\", callScope.callCtx.retLoadCfg)\n\t\tif err != nil {\n\t\t\tfncall.err = fmt.Errorf(\"could not get panic: %v\", err)\n\t\t\tbreak\n\t\t}\n\t\tfncall.panicvar.Name = \"~panic\"\n\n\tdefault:\n\t\t// Got an unknown protocol register value, this is probably bad but the safest thing\n\t\t// possible is to ignore it and hope it didn't matter.\n\t\tstack.callInjectionContinue = true\n\t\tfncallLog(\"unknown value of protocol register %#x\", regval)\n\t}\n\n\treturn false\n}\n\nfunc callInjectionComplete2(callScope *EvalScope, bi *BinaryInfo, fncall *functionCallState, regs Registers, thread Thread) {\n\t// Store the stack span of the currently running goroutine (which in Go >=\n\t// 1.15 might be different from the original injection goroutine) so that\n\t// later on we can use it to perform the escapeCheck","sourceCodeStart":936,"sourceCodeEnd":972,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/fncall.go#L936-L972","documentation":"During an injected function call that panicked, Delve enters the runtime's debug call protocol state debugCallRegReadPanic and must read the panic value (an interface{}) off the goroutine stack at SP+archoff (offset depends on architecture). When readStackVariable fails — because the type 'interface {}' cannot be found in DWARF, the stack memory is unreadable, or the value fails to load under the current load config — the call's error is set to \"could not get panic: %v\". The injected call cannot report which panic occurred, so the operation is aborted with the wrapped cause.","triggerScenarios":"Running a function call injection (e.g. via the 'call' command or expression evaluation) where the called function panics; the debugCallRegReadPanic protocol step then fails to read the panic value: DWARF info lacks the 'interface {}' type, the target's stack memory is unreadable (exited/corrupt process), or loadValue hits the MaxStringLen/MaxArrayRestriction limits of retLoadCfg.","commonSituations":"Debugging a stripped or partially-optimized binary where runtime type info is incomplete; target process dies mid-call-injection; extremely large string/struct in the panic value exceeding LoadConfig limits; debugging across Go runtime versions that changed the debug-call protocol stack layout.","solutions":["Inspect the wrapped cause (%v) to distinguish memory-read failure from missing DWARF type; fix that underlying issue first.","Rebuild the target binary without stripping and with a supported Go version so 'interface {}' DWARF type is present.","Increase LoadConfig limits (MaxStringLen, MaxStructFields, MaxRecvSteps) when the panic value is truncated/unreadable.","Re-attach or restart the target if the process exited or memory state is inconsistent.","Update Delve to match your Go version — debug-call protocol offsets change between releases."],"exampleFix":"// before (dlv config limits panic value load)\ndlv config max-string-len 64\n// after\n# start delve with larger limits so the panic interface value loads\ndlv debug --init init.txt\n# init.txt:\nconfig max-string-len 4096\nconfig max-array-values 512","handlingStrategy":"try-catch","validationCode":"// client-side (terminal): ensure binary has full DWARF and limits are generous\ndlv> config max-string-len 4096\ndlv> config max-array-values 512\ndlv> sources main.go // confirms binary has debug info","typeGuard":"// guard injected-call results before use\ntype callResult struct{ Err error; PanicVar *proc.Variable }\nfunc panicReadable(r callResult) bool {\n    return r.Err == nil || !strings.HasPrefix(r.Err.Error(), \"could not get panic:\")\n}","tryCatchPattern":"// wrap expression evaluation and detect this family\nv, err := dbg.EvalVariable(scope, expr, cfg)\nif err != nil && strings.Contains(err.Error(), \"could not get panic:\") {\n    // injected call panicked but panic value unreadable:\n    // restart session or raise LoadConfig limits and retry once\n}","preventionTips":["Build targets with full debug info (no -trimpath/-ldflags=\"-s -w\" stripping).","Keep Delve version in sync with the Go toolchain version used to build the target.","Raise max-string-len/max-array-values before injecting calls that can panic.","Avoid injecting calls that can panic; validate inputs at the breakpoint first.","Watch for target-thread death during injection; re-attach if state looks inconsistent."],"tags":["go","debugger","function-call-injection","panic","process-memory"],"backgroundTag":"function-call-injection-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}