go-delve/delve · warning
ctx variable not found
Error message
ctx variable not found
What it means
readSigtrampgoContext (pkg/proc/stack_sigtramp.go:45) recovers the interrupted thread's register state when the debugger stops inside the signal handler trampoline (runtime.sigtrampgo). It looks up the local variable `ctx` in the sigtrampgo frame's scope via DWARF variable information and dereferences it to find the ucontext. This error means no variable named `ctx` could be found in that frame, so Delve cannot reconstruct the registers and unwind out of the signal handler.
Source
Thrown at pkg/proc/stack_sigtramp.go:45
return nil
}
deref := func(v *Variable) (uint64, error) {
v.loadValue(loadSingleValue)
if v.Unreadable != nil {
return 0, fmt.Errorf("could not dereference %s: %v", v.Name, v.Unreadable)
}
if len(v.Children) < 1 {
return 0, fmt.Errorf("could not dereference %s (no children?)", v.Name)
}
logger.Debugf("%s address is %#x", v.Name, v.Children[0].Addr)
return v.Children[0].Addr, nil
}
getctxaddr := func() (uint64, error) {
ctxvar := findvar("ctx")
if ctxvar == nil {
return 0, errors.New("ctx variable not found")
}
addr, err := deref(ctxvar)
if err != nil {
return 0, err
}
return addr, nil
}
switch bi.GOOS {
case "windows":
epvar := findvar("ep")
if epvar == nil {
return nil, errors.New("ep variable not found")
}
epaddr, err := deref(epvar)
if err != nil {
return nil, err
}View on GitHub (pinned to a23773e6c3)
Solutions
- Keep DWARF symbols in the binary: do not pass -ldflags="-s -w"; rebuild with default flags or -gcflags='all=-N -l' for debugging.
- Verify the binary being debugged matches the running process (dlv attach) — a stale BinInfo makes the sigtrampgo frame unresolvable; relaunch the session.
- Update Delve; newer Go runtimes change where sigtrampgo stores ctx, and Delve must be updated to match your Go version.
- As a fallback, read thread registers directly (e.g. `regs` command) instead of relying on the signal-context reconstruction; or continue past the signal.
- If you only need the fault location, inspect the SIGSEGV address / goroutine state rather than unwinding through sigtrampgo.
Example fix
// before: stripped binary stops in sigtrampgo, ctx is not in DWARF go build -ldflags="-s -w" -o app . // after: keep debug info so the signal context can be recovered go build -o app . # or: go build -gcflags="all=-N -l" -o app .
Defensive patterns
Strategy: try-catch
Validate before calling
// Before debugging, ensure the binary retains DWARF info: // go tool buildid <binary> && go version -m <binary> // and confirm it was NOT built with -ldflags="-s -w".
Try / catch
try {
frames = client.Stacktrace(threadID, depth)
} catch (err) {
if (strings.Contains(err.Error(), "ctx variable not found")) {
// stopped in sigtrampgo without recoverable signal context;
// fall back to raw register state or continue past the signal
regs, regErr := client.ListThreadRegs(threadID, false)
_ = regs
_ = regErr
} else {
return err
}
} Prevention
- Never strip symbols (-ldflags="-s -w") on binaries you will debug
- Match Delve version to Go version before debugging signal-heavy code
- Verify attach target binary matches the launched binary byte-for-byte
- Handle SIGSEGV in tests so the debugger does not stop inside sigtrampgo
When it happens
Trigger: Triggered when the debuggee is stopped in runtime.sigtrampgo (signal delivery: SIGSEGV, SIGBUS, or Go's own signal-based preemption) on Linux/FreeBSD/Darwin, and scope.Locals(0, "ctx") returns nothing named `ctx`. Causes: (1) Go runtime built without a resolvable DWARF entry for ctx (highly optimized runtime, ctx kept only in registers); (2) binary info mismatch — the sigtrampgo frame is attributed to a different/mismatched binary; (3) the frame is not actually sigtrampgo (misattributed PC), so `ctx` never exists in scope; (4) stripped or partial DWARF in the runtime portion of the binary.
Common situations: Debugging a program that received SIGSEGV and Delve stops the thread inside the signal trampoline; stepping while Go's async preemption signal (SIGURG) lands; core-dump or attach debugging where the stopped PC is in sigtrampgo; debugging a binary whose runtime was compiled with -ldflags="-s -w" or otherwise stripped symbols.
Related errors
- ep variable not found
- unable to find function context
- unable to find locals: no debug information present in binar
- malformed map type: buckets, oldbuckets or overflow field no
- malformed variable DIE (name)
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/7e17def731c974bf.
Report an issue: GitHub.