microsoft/garnet · error · GarnetException

ERR value is not an integer or out of range.

Error message

ERR value is not an integer or out of range.

What it means

Thrown by GetBitfield when TryValidateBitfieldOffset(offset, encoding, ...) fails - the offset/encoding combination is invalid (zero bit count, negative offset, overflow, or end-offset beyond the 512 MiB-payload bit limit). The message is the standard Redis range error. The BITFIELD command parser already runs the same validation (BitmapCommands.cs) and rejects bad offsets with a RESP error before reaching here, so this throw is a defensive backstop for an internal path that bypassed parsing validation.

Source

Thrown at libs/server/Resp/Bitmap/BitmapManagerBitfield.cs:329

            if (curr < cend) *curr++ = (byte)((tmp >> 24) & 0xFF);
            if (curr < cend) *curr++ = (byte)((tmp >> 16) & 0xFF);
            if (curr < cend) *curr++ = (byte)((tmp >> 8) & 0xFF);
            if (curr < cend) *curr++ = (byte)((tmp >> 0) & 0xFF);
        }

        /// <summary>
        /// Implementation of bitfield GET operation.
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="bitmapLength"></param>
        /// <param name="offset"></param>
        /// <param name="encoding"></param>
        /// <param name="signed"></param>
        /// <returns></returns>
        private static long GetBitfield(byte* bitmap, long bitmapLength, long offset, byte encoding, bool signed)
        {
            if (!TryValidateBitfieldOffset(offset, encoding, multiplyOffset: false, out offset, out var endOffset))
                throw new GarnetException("ERR value is not an integer or out of range.");

            var byteIndexStart = Index(offset);
            var byteIndexEnd = Index(endOffset) + 1;
            var buf = stackalloc byte[8];
            *(ulong*)buf = 0;

            // Simple case value is beyond current length
            if (byteIndexStart >= bitmapLength) return 0;

            var vend = bitmap + bitmapLength;
            var curr = bitmap + byteIndexStart;
            var cend = bitmap + byteIndexEnd < vend ? (bitmap + byteIndexEnd) : vend;
            var returnValue = GetValue(ref buf, ref curr, cend, vend, bitmapLength, offset, encoding, signed);

            return returnValue;
        }

        /// <summary>

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Use a valid encoding (e.g., u8, i16, width 1-64, non-zero).
  2. Keep offsets non-negative and within the bitmap limit; watch #-multiplied offsets.
  3. Update Garnet - older builds routed more cases through this throw.

Example fix

# before
BITFIELD key GET u0 0          # invalid: zero-width type
# after
BITFIELD key GET u8 0
Defensive patterns

Strategy: validation

Validate before calling

// Validate bitfield encoding + offset before issuing BITFIELD
if (bitCount < 1 || bitCount > 64) throw new ArgumentException("bad bitfield width");
if (offset < 0) throw new ArgumentException("negative offset");
// for #-multiplied: ensure offset*bitCount stays under the 512MiB*8-1 bit limit

Try / catch

catch (GarnetException ex) when (ex.Message == "ERR value is not an integer or out of range.") {
    return BadRequest(ex.Message); // standard client-side range error
}

Prevention

When it happens

Trigger: GetBitfield is called with an offset/encoding that TryValidateBitfieldOffset rejects (e.g., u0 encoding, negative offset, or #-multiplied offset that overflows past the bitmap limit).

Common situations: A client BITFIELD GET with a malformed type (zero width) or an enormous offset; an internal caller invoking GetBitfield directly without the parser's validation.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/a14b8287e01c8d2e. Report an issue: GitHub.