go-delve/delve · error

operator %s not defined on %s

Error message

operator %s not defined on %s

What it means

Once constant folding is ruled out, compareOp handles comparisons on loaded variables. Only == and != are defined for most kinds; ordering operators (<, <=, >, >=) are only valid on numbers and strings. When an ordering operator reaches this point with a kind like bool, pointer, or struct, Delve reports that the operator is not defined on that kind.

Source

Thrown at pkg/proc/eval.go:2635

				return false, nil
			case token.NEQ:
				return true, nil
			}
		}
		if xv.Kind == reflect.String {
			xv.loadValue(loadFullValueLongerStrings)
		}
		if yv.Kind == reflect.String {
			yv.loadValue(loadFullValueLongerStrings)
		}
		if int64(len(constant.StringVal(xv.Value))) != xv.Len || int64(len(constant.StringVal(yv.Value))) != yv.Len {
			return false, errors.New("string too long for comparison")
		}
		return constantCompare(op, xv.Value, yv.Value)
	}

	if op != token.EQL && op != token.NEQ {
		return false, fmt.Errorf("operator %s not defined on %s", op.String(), xv.Kind.String())
	}

	var eql bool
	var err error

	if xv == nilVariable {
		switch op {
		case token.EQL:
			return yv.isNil(), nil
		case token.NEQ:
			return !yv.isNil(), nil
		}
	}

	if yv == nilVariable {
		switch op {
		case token.EQL:
			return xv.isNil(), nil

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Use == or != for kinds without ordering, or compare a numeric member: `p a.field < b.field`.
  2. Convert pointers via uintptr for debugging purposes: `p uintptr(p1) < uintptr(p2)`.
  3. Check the kind with `print x` before using relational operators.

Example fix

// before
p p1 < p2
// after
p uintptr(p1) < uintptr(p2)
Defensive patterns

Strategy: validation

Validate before calling

// only numbers and strings support ordering
ordered := map[reflect.Kind]bool{
    reflect.Int: true, reflect.Int8: true, reflect.Int16: true, reflect.Int32: true, reflect.Int64: true,
    reflect.Uint: true, reflect.Uint8: true, reflect.Uint16: true, reflect.Uint32: true, reflect.Uint64: true,
    reflect.Float32: true, reflect.Float64: true, reflect.String: true,
}
if !ordered[v.Kind] {
    // use == / != or compare a numeric field instead
}

Type guard

func supportsOrdering(k reflect.Kind) bool {
    switch k {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
        reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
        reflect.Float32, reflect.Float64, reflect.String:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Evaluating `p ptr1 < ptr2`, `p boolVar <= boolVar2`, or any relational op on non-ordered kinds; triggered when op is not EQL/NEQ and the operands weren't handled by the constant path.

Common situations: Trying to order pointers or booleans (illegal in Go too), or comparing structs with <; usually a misunderstanding that the debugger follows the same operator rules as the language.

Related errors


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