go-delve/delve · error

unable to find locals: no debug information present in binar

Error message

unable to find locals: no debug information present in binary

What it means

simpleLocals refuses to enumerate locals when the binary image backing the scope has no DWARF debug info (image().Stripped()). Without debug info there are no variable DIEs to decode, so delve explicitly reports the binary is stripped rather than returning an empty list.

Source

Thrown at pkg/proc/eval.go:425

	if len(scope.rangeFrames) > 0 {
		scope.rangeFrames = scope.rangeFrames[2:] // skip the first frame and its return frame
	}
	scope.enclosingRangeScopes = make([]*EvalScope, len(scope.rangeFrames)/2)
	return nil
}

// simpleLocals returns all local variables in 'scope'.
// This function does not try to merge the scopes of range-over-func closure
// bodies with their enclosing function, for that use (*EvalScope).Locals or
// (*EvalScope).FindLocal instead.
// If wantedName is specified only variables called wantedName or "&"+wantedName are returned.
func (scope *EvalScope) simpleLocals(flags localsFlags, wantedName string) ([]*Variable, error) {
	if scope.Fn == nil {
		return nil, errors.New("unable to find function context")
	}

	if scope.image().Stripped() {
		return nil, errors.New("unable to find locals: no debug information present in binary")
	}

	trustArgOrder := (flags&localsTrustArgOrder != 0) && scope.BinInfo.Producer() != "" && goversion.ProducerAfterOrEqual(scope.BinInfo.Producer(), 1, 12) && scope.Fn != nil && (scope.PC == scope.Fn.Entry)

	dwarfTree, err := scope.image().getDwarfTree(scope.Fn.offset)
	if err != nil {
		return nil, err
	}

	variablesFlags := reader.VariablesOnlyVisible | reader.VariablesSkipInlinedSubroutines
	if flags&localsNoDeclLineCheck != 0 {
		variablesFlags = reader.VariablesNoDeclLineCheck
	}
	if scope.BinInfo.Producer() != "" && goversion.ProducerAfterOrEqual(scope.BinInfo.Producer(), 1, 15) {
		variablesFlags |= reader.VariablesTrustDeclLine
	}

	varEntries := reader.Variables(dwarfTree, scope.PC, scope.Line, variablesFlags)

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Rebuild the binary with debug info: go build without -s and -w linker flags (e.g. go build -gcflags="all=-N -l").
  2. Verify with `go tool nm <binary>` or `file <binary>` ('not stripped') that DWARF sections exist before debugging.
  3. If the binary cannot be rebuilt, debug a non-stipped copy of the same commit (addresses match when build flags otherwise identical).
  4. Check BinInfo.Producer()/image().Stripped() upfront in tooling and warn users instead of failing mid-session.

Example fix

// before
$ go build -ldflags="-s -w" -o app .
$ dlv exec app
// after
$ go build -gcflags="all=-N -l" -o app .
$ dlv exec app
Defensive patterns

Strategy: validation

Validate before calling

if scope.BinInfo == nil || scope.image().Stripped() {
    return fmt.Errorf("binary is stripped; rebuild without -s -w")
}

Type guard

func debugInfoAvailable(scope *proc.EvalScope) bool {
    return scope != nil && scope.Fn != nil && !scope.image().Stripped()
}

Try / catch

vars, err := scope.Locals(0)
if err != nil && strings.Contains(err.Error(), "no debug information") {
    return fmt.Errorf("rebuild the binary with debug info: go build (no -s -w)")
}

Prevention

When it happens

Trigger: Calling Locals() (or FindLocal) while debugging a binary built with -ldflags "-s -w" or otherwise stripped of .debug_* sections; attaching to a release-build process; core dump of a stripped binary.

Common situations: Debugging production/CI builds that strip symbols; go build with -trimpath plus -s -w; attaching to vendor-shipped Go binaries; mixed builds where the main module is stripped but dependencies are not.

Related errors


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