go-delve/delve · error
internal debugger error: depth check error at instruction %d
Error message
internal debugger error: depth check error at instruction %d: expected depth %d have %d (jump target) %s
What it means
An internal consistency check in Delve's expression-VM compiler (pkg/proc/evalop/evalcompile.go) failed: when computing operand-stack depths, a jump target instruction was reached with a different stack depth than previously recorded. This is a compiler invariant violation, not something caused by a syntactically valid user expression; it indicates a bug in Delve's opcode generation or a genuinely malformed generated program.
Source
Thrown at pkg/proc/evalop/evalcompile.go:259
// checks that they have enough arguments to execute. For instructions that
// can be reached through multiple paths (because of a jump) it checks that
// all paths reach the instruction with the same stack depth.
// Finally it checks that the stack depth after all instructions have
// executed is equal to endDepth.
func (ctx *compileCtx) depthCheck(endDepth int) error {
depth := make([]int, len(ctx.ops)+1) // depth[i] is the depth of the stack before i-th instruction
for i := range depth {
depth[i] = -1
}
depth[0] = 0
var err error
checkAndSet := func(j, d int) { // sets depth[j] to d after checking that we can
if depth[j] < 0 {
depth[j] = d
}
if d != depth[j] {
err = fmt.Errorf("internal debugger error: depth check error at instruction %d: expected depth %d have %d (jump target)\n%s", j, d, depth[j], Listing(depth, ctx.ops))
}
}
debugPinnerSeen := false
for i, op := range ctx.ops {
npop, npush := op.depthCheck()
if depth[i] < npop {
return fmt.Errorf("internal debugger error: depth check error at instruction %d: expected at least %d have %d\n%s", i, npop, depth[i], Listing(depth, ctx.ops))
}
d := depth[i] - npop + npush
checkAndSet(i+1, d)
switch op := op.(type) {
case *Jump:
checkAndSet(op.Target, d)
case *CallInjectionStartSpecial:
debugPinnerSeen = true
case *CallInjectionComplete:View on GitHub (pinned to a23773e6c3)
Solutions
- Update to the latest delve release — check for known fixed issues around evalop/depthCheck
- Simplify the expression (remove nesting, casts, calls) until it evaluates, then file a bug with the minimal reproducing expression and `Listing` output embedded in the error
- Temporarily replace the failing breakpoint condition with a simpler one and inspect state manually
Defensive patterns
Strategy: try-catch
Try / catch
out, err := evalExpr(userExpr)
if err != nil && strings.HasPrefix(err.Error(), "internal debugger error") {
// not a user mistake: simplify or report
out, err = evalExpr(simplify(userExpr))
log.Printf("delve internal error, please report: %v", err)
} Prevention
- Keep delve updated; internal invariant errors are compiler bugs fixed upstream
- Avoid exotic combinations (calls + control flow) in breakpoint conditions until validated
- Capture the full error (it embeds the instruction Listing) when filing a bug
When it happens
Trigger: Calling CompileAST or CompileSet on an expression whose compiled op sequence contains a Jump whose target's depth does not match the depth flowing into it — i.e. a Delve bug in evalop compilation, possibly triggered by an unusual expression shape that hits an untested compiler path.
Common situations: Rare; typically seen after a delve version regression, when testing experimental expression features (e.g. delve.catch, call injection combined with control flow), or when a breakpoint condition exercises a newly added opcode combination.
Related errors
- internal debugger error: depth check error at instruction %d
- internal debugger error: depth check failed: depth at the en
- internal debugger error: pinning call injection seen before
- hardware breakpoints exhausted
- break on read only not supported
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/de093ca0f16450f1.
Report an issue: GitHub.