go-delve/delve · error

condition expression unreadable: %v

Error message

condition expression unreadable: %v

What it means

Delve evaluates a conditional breakpoint's expression and loads the resulting value from the debuggee's memory. If the loaded value is unreadable (bad address, process gone, corrupted memory), the condition cannot be evaluated, so Delve aborts evaluation with this error instead of silently deciding the condition is false.

Source

Thrown at pkg/proc/breakpoints.go:528

	v, err := stack.result(nil)
	if err != nil {
		if stack.disabledErrors {
			return false, nil
		}
		return true, fmt.Errorf("error evaluating expression: %v", err)
	}
	if v.Kind != reflect.Bool {
		if stack.disabledErrors {
			return false, nil
		}
		return true, errors.New("condition expression not boolean")
	}
	v.loadValue(LoadFullValue())
	if v.Unreadable != nil {
		if stack.disabledErrors {
			return false, nil
		}
		return true, fmt.Errorf("condition expression unreadable: %v", v.Unreadable)
	}
	return constant.BoolVal(v.Value), nil
}

// NoBreakpointError is returned when trying to
// clear a breakpoint that does not exist.
type NoBreakpointError struct {
	Addr uint64
}

func (nbp NoBreakpointError) Error() string {
	return fmt.Sprintf("no breakpoint at %#v", nbp.Addr)
}

// BreakpointMap represents an (address, breakpoint) map.
type BreakpointMap struct {
	M map[uint64]*Breakpoint

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Fix the condition expression so it only references variables valid and readable at the breakpoint location
  2. Check the wrapped Unreadable message (%v suffix) to identify the bad address or variable and guard the condition with nil checks (e.g. 'p != nil && p.x == 1')
  3. Remove the condition and filter manually in the CLI instead of evaluating a fragile expression
  4. Rebuild the target binary with optimizations disabled (-gcflags='all=-N -l') so variables stay readable

Example fix

// before
break cond p.x == 1
// after
break cond p != nil && p.x == 1
Defensive patterns

Strategy: try-catch

Validate before calling

v, err := scope.EvalExpression(expr, LoadFullValue())
if err != nil || v.Unreadable != nil { /* fix condition before attaching */ }

Type guard

func conditionReadable(v *proc.Variable) bool { return v != nil && v.Unreadable == nil && v.Value != nil }

Try / catch

bp, err := db.SetBreakpoint(...)
// at hit time the error surfaces as evaluate failure:
if err != nil && strings.Contains(err.Error(), "condition expression unreadable") { db.ClearBreakpoint(id); /* re-set with guarded condition */ }

Prevention

When it happens

Trigger: Calling SetBreakpoint/checkCond with an expression like 'bpcond==1' whose variable cannot be read at hit time (uninitialized pointer, out-of-scope variable, stale stack frame), i.e. scope.evalExpression succeeds but v.loadValue(LoadFullValue()) sets v.Unreadable.

Common situations: Breakpoint condition references a variable that is optimized out or whose backing memory is not mapped yet; attaching to a process whose pages are swapped/unmapped; condition written for one function but breakpoint also placed at other call sites where the variable is invalid.

Related errors


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