microsoft/garnet · error · GarnetException

RI.GET: invalid arguments.

Error message

RI.GET: invalid arguments.

What it means

RI.GET (RangeIndex GET) throws when the BfTree read into the output buffer returns InvalidArguments. This is the first of two RI.GET error paths — the direct SpanByte buffer path. It indicates the field span passed to the native read was structurally invalid (empty/null) or the tree handle was in a bad state.

Source

Thrown at libs/server/Storage/Session/MainStore/RangeIndexOps.cs:315

                var bufLen = output.SpanByteAndMemory.Length;
                var maxValueSize = (int)stub.MaxRecordSize;

                const int optimisticHeaderSize = 1 + 1 + 2; // $N\r\n
                const int trailerSize = 2; // \r\n
                const int maxHeaderSize = 1 + 10 + 2; // $<maxDigits>\r\n
                var minBufferNeeded = maxHeaderSize + maxValueSize + trailerSize; // $<maxDigits>\r\n + value + \r\n

                if (bufLen >= minBufferNeeded)
                {
                    // Read BfTree value directly into output buffer past the header reservation
                    var bufStart = output.SpanByteAndMemory.SpanByte.ToPointer();
                    var valueStart = bufStart + optimisticHeaderSize;
                    var readResult = BfTreeService.ReadByPtrInto(stub.TreeHandle, field, valueStart, maxValueSize, out var bytesWritten);

                    if (readResult == BfTreeReadResult.InvalidArguments)
                    {
                        logger?.LogError("RI.GET: invalid arguments for a {fieldLen}-byte field.", field.Length);
                        throw new GarnetException("RI.GET: invalid arguments.");
                    }

                    if (readResult != BfTreeReadResult.Found || bytesWritten < 0)
                    {
                        result = RangeIndexResult.NotFound;
                        return GarnetStatus.OK;
                    }

                    // Backfill exact header, append trailer, shift to eliminate gap
                    var numLength = NumUtils.CountDigits(bytesWritten);
                    var actualHeaderSize = 1 + numLength + 2; // $N\r\n
                    var actualValueStart = bufStart + actualHeaderSize;
                    if (valueStart != actualValueStart)
                        Buffer.MemoryCopy(valueStart, actualValueStart, bytesWritten, bytesWritten);

                    var tmp = bufStart;
                    *tmp++ = (byte)'$';
                    NumUtils.WriteInt32(bytesWritten, numLength, ref tmp);

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Ensure the field argument to RI.GET is non-empty.
  2. If the error persists with a valid field, recreate the range index to rule out corruption.
  3. Check server logs for the logged field length to confirm what was passed.

Example fix

// before
RI.GET myindex ""

// after
RI.GET myindex "field1"
Defensive patterns

Strategy: validation

Validate before calling

if (field == null || field.Length == 0)
    throw new ArgumentException("RI.GET field must be non-empty.");

Prevention

When it happens

Trigger: Calling the RI.GET operation when BfTreeService.ReadByPtrInto returns BfTreeReadResult.InvalidArguments on the direct buffer path (output.SpanByteAndMemory has a SpanByte backing). Occurs with an empty field, or a corrupted tree handle.

Common situations: Client sending RI.GET with an empty field name; argument parsing bug producing zero-length span; corrupted range index after crash.

Related errors


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