go-delve/delve · error

shift count type %s, must be unsigned integer

Error message

shift count type %s, must be unsigned integer

What it means

Delve's expression evaluator requires the right-hand operand of a shift (<< or >>) to be an unsigned integer. When the shift-count variable's reflect.Kind is not one of the signed int kinds that passed the earlier checks (i.e. it's a float, string, struct, etc.), the evaluator rejects it with this message. It mirrors Go's compile-time rule that shift counts must be unsigned integers.

Source

Thrown at pkg/proc/eval.go:2449

	if yv == nilVariable {
		return nil, negotiateTypeNil(op, xv)
	}

	if op == token.SHR || op == token.SHL {
		if xv.Value == nil || xv.Value.Kind() != constant.Int {
			return nil, fmt.Errorf("shift of type %s", xv.Kind)
		}

		switch yv.Kind {
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			// ok
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if constant.Sign(yv.Value) < 0 {
				return nil, errors.New("shift count must not be negative")
			}
		default:
			return nil, fmt.Errorf("shift count type %s, must be unsigned integer", yv.Kind.String())
		}

		return xv.DwarfType, nil
	}

	if xv.DwarfType == nil && yv.DwarfType == nil {
		return nil, nil
	}

	if xv.DwarfType != nil && yv.DwarfType != nil {
		if xv.DwarfType.String() != yv.DwarfType.String() {
			return nil, fmt.Errorf("mismatched types %q and %q", xv.DwarfType.String(), yv.DwarfType.String())
		}
		return xv.DwarfType, nil
	} else if xv.DwarfType != nil && yv.DwarfType == nil {
		if err := yv.isType(xv.DwarfType, xv.Kind); err != nil {
			return nil, err
		}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Cast the shift count to an unsigned integer: `x << uint(y)`.
  2. If the count is a float, convert to int first: `x << uint(int(f))`.
  3. Inspect the count variable (`print y`) to confirm its type is what you expect.

Example fix

// before
p x << y        // y is float64
// after
p x << uint(y)
Defensive patterns

Strategy: validation

Validate before calling

// before: x << y
if v, err := eval("y"); err == nil {
    switch v.Kind {
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
        // ok
    default:
        y = uint(y) // cast the shift count before shifting
    }
}

Type guard

func isUnsignedKind(k reflect.Kind) bool {
    switch k {
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Evaluating an expression like `x << y` in the debugger where y is a negative int (handled separately), a float64, or a non-numeric kind such as string, bool, slice or struct. Reached via EvalScope.evaluateBinaryOp with op token.SHL/token.SHR and the shift-count variable's Kind outside the int/uint set.

Common situations: Debugging session where the user writes `buf >> 4.0` or `flags << someStringVar`; typical for someone testing bit-manipulation logic interactively and forgetting the operand types differ from what they assume in source.

Related errors


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