go-delve/delve · warning

%v

Error message

%v

What it means

constantUnaryOp wraps go/constant's constant.UnaryOp and converts any panic it triggers into an error via fmt.Errorf("%v", recover()). The message text is therefore whatever the go/constant runtime panicked with (e.g. an invalid unary operation on the constant's kind). It is a defensive wrapper so a malformed constant never crashes the debugger.

Source

Thrown at pkg/proc/eval.go:2363

	}

	stack.push(xev.pointerToVariable())
}

func (v *Variable) pointerToVariable() *Variable {
	v.OnlyAddr = true

	rv := v.newVariable("", 0, godwarf.FakePointerType(v.DwarfType, int64(v.bi.Arch.PtrSize())), v.mem)
	rv.Children = []Variable{*v}
	rv.loaded = true

	return rv
}

func constantUnaryOp(op token.Token, y constant.Value) (r constant.Value, err error) {
	defer func() {
		if ierr := recover(); ierr != nil {
			err = fmt.Errorf("%v", ierr)
		}
	}()
	r = constant.UnaryOp(op, y, 0)
	return
}

func constantBinaryOp(op token.Token, x, y constant.Value) (r constant.Value, err error) {
	defer func() {
		if ierr := recover(); ierr != nil {
			err = fmt.Errorf("%v", ierr)
		}
	}()
	switch op {
	case token.SHL, token.SHR:
		n, _ := constant.Uint64Val(y)
		r = constant.Shift(x, op, uint(n))
	default:
		r = constant.BinaryOp(x, op, y)

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Check the operand type with `print x` and use an operator valid for it (negate ints/floats, `!` for bools, `^` for ints).
  2. If the operand is a string, convert first (e.g. use `len(x)` or parse to a number) instead of applying arithmetic.
  3. If the value itself looks corrupt, re-read it fresh (`print x`) or restart the session; the constant may come from a bad memory read.
  4. Report persistent panics with the exact expression to go-delve/delve — the panic text comes from go/constant and may indicate an unhandled value kind.

Example fix

// before
(dlv) print -"hello"
// panic converted to: <go/constant panic text>

// after
(dlv) print len("hello") // string ops via valid builtins
(dlv) print -n // unary minus only on numeric values
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the operand supports the unary op:
(dlv) print x        // string? bool? use the right operator
// numeric -> -x or ^x; bool -> !x

Type guard

func supportsUnaryMinus(v interface{}) bool {
    switch reflect.TypeOf(v).Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
        reflect.Float32, reflect.Float64:
        return true
    }
    return false
}

Try / catch

// Delve already converts the panic to an error; on the client side (rpc2):
res, err := client.EvalVariable(scope, expr, cfg)
if err != nil && strings.Contains(err.Error(), "invalid operation") {
    // re-issue with a corrected expression
}

Prevention

When it happens

Trigger: Evaluating a unary expression (-x, +x, ^x, !x) at the debugger prompt where xv.Value is a constant.Value that go/constant cannot handle for that operator — e.g. `-"string"`, `^1.5`, or a constant produced from a corrupt/odd value read from debuggee memory.

Common situations: Applying numeric negation to a string constant, bitwise complement of a float, or exotic unary ops on values reconstructed from unusual memory states. Rare in normal use because earlier checks catch nil values and special floats.

Related errors


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