go-delve/delve · warning

ep variable not found

Error message

ep variable not found

What it means

On Windows, readSigtrampgoContext (pkg/proc/stack_sigtramp.go:58) recovers the interrupted thread's registers when stopped inside runtime.sigtrampgo by locating the local variable `ep` (a *exceptionpointers passed into sigtrampgo), dereferencing it, and walking to the CONTEXT structure. This error means no variable named `ep` was found in the frame's local scope, so Delve cannot decode the Windows exception context and unwind the stack through the signal handler.

Source

Thrown at pkg/proc/stack_sigtramp.go:58

	}

	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
		}
		switch bi.Arch.Name {
		case "amd64":
			return sigtrampContextWindowsAMD64(it.mem, epaddr)
		case "arm64":
			return sigtrampContextWindowsARM64(it.mem, epaddr)
		default:
			return nil, errors.New("not implemented")
		}
	case "linux":
		addr, err := getctxaddr()
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Upgrade Delve to the latest release so its expectations about sigtrampgo's `ep` parameter match your Go version.
  2. Rebuild the program keeping symbol/debug info (avoid -ldflags="-s -w"); unoptimized builds (-gcflags='all=-N -l') make locals reliably resolvable.
  3. Ensure dlv attaches to a process built from exactly the binary it was given; relaunch via dlv exec to avoid symbol mismatch.
  4. Continue past the exception or inspect thread state via `regs` as a workaround instead of unwinding through the trampoline.
  5. If reproducible, file a Delve issue with Windows version, Go version, and --log-output=debug output.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

// On Windows, before debugging, confirm symbol info is present and versions match:
// go version -m <binary.exe>  (shows build flags; reject -ldflags="-s -w" builds)
// dlv version  vs  go version  (keep within supported range)

Try / catch

try {
    frames = client.Stacktrace(threadID, depth)
} catch (err) {
    if (strings.Contains(err.Error(), "ep variable not found")) {
        // Windows sigtrampgo context unrecoverable; use raw regs or continue
        regs, regErr := client.ListThreadRegs(threadID, false)
        _ = regs
        _ = regErr
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Raised when the debuggee is a Windows process stopped in runtime.sigtrampgo (e.g. after a Windows exception such as an access violation) and scope.Locals(0, "ep") finds nothing named `ep`. Causes: (1) the Go runtime binary lacks DWARF/DWARF-equivalent variable info for `ep` (stripped or highly optimized runtime); (2) binary/process mismatch on attach so the frame scope is resolved against wrong symbols; (3) the Go version's sigtrampgo no longer names the parameter `ep` while the installed Delve is older (or vice versa); (4) the stopped frame is misattributed (PC not actually in sigtrampgo).

Common situations: Debugging a Windows Go program that hit an access violation and the thread stops in the exception trampoline; attaching to a Windows process whose Go runtime was built stripped; running an older Delve against a newer Go release where sigtrampgo's signature/locals changed (Go 1.21+ changes to exception handling); core/exception debugging in IDEs via DAP on Windows.

Related errors


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