go-delve/delve · error

internal debugger error: depth check failed: depth at the en

Error message

internal debugger error: depth check failed: depth at the end is not %d (got %d)
%s

What it means

Final check of the expression compiler's depth verification (depthCheck in pkg/proc/evalop/evalcompile.go): after compiling the whole expression, the operand stack depth must equal `endDepth` (normally 1 result for an evaluation, per CompileAST/CompileSet); a different depth means the compiled program does not produce the expected number of results. Like the other depth checks, it flags a compiler bug, not user input problems.

Source

Thrown at pkg/proc/evalop/evalcompile.go:288

		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:
			if op.DoPinning && !debugPinnerSeen {
				err = fmt.Errorf("internal debugger error: pinning call injection seen before call to %s at instruction %d", DebugPinnerFunctionName, i)
			}
		}
		if err != nil {
			return err
		}
	}

	if depth[len(ctx.ops)] != endDepth {
		return fmt.Errorf("internal debugger error: depth check failed: depth at the end is not %d (got %d)\n%s", depth[len(ctx.ops)], endDepth, Listing(depth, ctx.ops))
	}
	return nil
}

func (ctx *compileCtx) compileAST(t ast.Expr, toplevel bool) error {
	switch node := t.(type) {
	case *ast.CallExpr:
		if f, ok := node.Fun.(*ast.SelectorExpr); ok && ctx.flags&BreakpointCondition != 0 {
			const catch = "catch"
			if ident, ok := f.X.(*ast.Ident); ok && ident.Name == DelvePackage && f.Sel.Name == catch {
				if !toplevel {
					return fmt.Errorf("%s.%s can only be used at toplevel", DelvePackage, catch)
				}
				if len(node.Args) != 1 {
					return fmt.Errorf("wrong number of arguments for %s.%s", DelvePackage, catch)
				}
				ctx.pushOp(&DisableErrors{})
				return ctx.compileAST(node.Args[0], false)

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Update delve to the latest stable release
  2. Rewrite the failing expression as simpler separate evaluations
  3. Report the reproducing expression and error listing to go-delve/delve
Defensive patterns

Strategy: try-catch

Try / catch

if err != nil && strings.Contains(err.Error(), "depth at the end is not") {
    // compiler produced unbalanced stack: simplify and retry
    return evalSplit(expr)
}

Prevention

When it happens

Trigger: CompileAST or CompileSet on an expression whose compiled ops leave a different number of values on the stack than required — e.g. an opcode pushes/pops asymmetrically due to a compile bug in an untested expression construct.

Common situations: Appears after delve regressions in the evalop VM, when testing pre-release delve versions, or when expressions combine rare features (casts, delve.catch, call injection) whose opcode emission doesn't balance the stack.

Related errors


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