go-delve/delve · error

could not get panic: %v

Error message

could not get panic: %v

What it means

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.

Source

Thrown at pkg/proc/fncall.go:954

			fncall.addrsToPin = slices.Compact(fncall.addrsToPin)

			return false // will continue with evalop.CallInjectionComplete2
		}

		callInjectionComplete2(callScope, bi, fncall, regs, thread)

	case debugCallRegReadPanic: // 2
		// read panic value from stack
		stack.callInjectionContinue = true
		archoff := uint64(0)
		if bi.Arch.Name == "arm64" || bi.Arch.Name == "loong64" {
			archoff = 8
		} else if bi.Arch.Name == "ppc64le" {
			archoff = 32
		}
		fncall.panicvar, err = readStackVariable(p, thread, regs, archoff, "interface {}", callScope.callCtx.retLoadCfg)
		if err != nil {
			fncall.err = fmt.Errorf("could not get panic: %v", err)
			break
		}
		fncall.panicvar.Name = "~panic"

	default:
		// Got an unknown protocol register value, this is probably bad but the safest thing
		// possible is to ignore it and hope it didn't matter.
		stack.callInjectionContinue = true
		fncallLog("unknown value of protocol register %#x", regval)
	}

	return false
}

func callInjectionComplete2(callScope *EvalScope, bi *BinaryInfo, fncall *functionCallState, regs Registers, thread Thread) {
	// Store the stack span of the currently running goroutine (which in Go >=
	// 1.15 might be different from the original injection goroutine) so that
	// later on we can use it to perform the escapeCheck

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Inspect the wrapped cause (%v) to distinguish memory-read failure from missing DWARF type; fix that underlying issue first.
  2. Rebuild the target binary without stripping and with a supported Go version so 'interface {}' DWARF type is present.
  3. Increase LoadConfig limits (MaxStringLen, MaxStructFields, MaxRecvSteps) when the panic value is truncated/unreadable.
  4. Re-attach or restart the target if the process exited or memory state is inconsistent.
  5. Update Delve to match your Go version — debug-call protocol offsets change between releases.

Example fix

// before (dlv config limits panic value load)
dlv config max-string-len 64
// after
# start delve with larger limits so the panic interface value loads
dlv debug --init init.txt
# init.txt:
config max-string-len 4096
config max-array-values 512
Defensive patterns

Strategy: try-catch

Validate before calling

// client-side (terminal): ensure binary has full DWARF and limits are generous
dlv> config max-string-len 4096
dlv> config max-array-values 512
dlv> sources main.go // confirms binary has debug info

Type guard

// guard injected-call results before use
type callResult struct{ Err error; PanicVar *proc.Variable }
func panicReadable(r callResult) bool {
    return r.Err == nil || !strings.HasPrefix(r.Err.Error(), "could not get panic:")
}

Try / catch

// wrap expression evaluation and detect this family
v, err := dbg.EvalVariable(scope, expr, cfg)
if err != nil && strings.Contains(err.Error(), "could not get panic:") {
    // injected call panicked but panic value unreadable:
    // restart session or raise LoadConfig limits and retry once
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/04d6f083ae34d54f. Report an issue: GitHub.