microsoft/garnet · error · GarnetException

BITOP DIFF operation requires at least two source bitmaps

Error message

BITOP DIFF operation requires at least two source bitmaps

What it means

Thrown by InvokeBitOperationUnsafe when BITOP DIFF is invoked with exactly one resolved source bitmap (srcCount == 1). DIFF (and-not) is n-ary and needs >= 2 operands; with one source it is undefined, so Garnet rejects it. The command parser already rejects BITOP DIFF with fewer than 3 tokens (dest + <2 sources), but that check counts arguments, not existing keys - so the throw fires when you supply >=2 source key names but only one actually exists in the store (keysFound == 1).

Source

Thrown at libs/server/Resp/Bitmap/BitmapManagerBitOp.cs:35

public static void InvokeBitOperationUnsafe(BitmapOperation op, int srcCount, byte** srcPtrs, byte** srcEndPtrs, byte* dstPtr, int dstLength, int shortestSrcLength)
{
    Debug.Assert(op is BitmapOperation.NOT or BitmapOperation.AND or BitmapOperation.OR or BitmapOperation.XOR or BitmapOperation.DIFF);
    Debug.Assert(srcCount > 0);
    Debug.Assert(dstLength >= 0 && shortestSrcLength >= 0);
    Debug.Assert(dstLength >= shortestSrcLength);

    if (srcCount == 1)
    {
        if (op == BitmapOperation.DIFF) throw new GarnetException("BITOP DIFF operation requires at least two source bitmaps");

        var srcBitmap = new ReadOnlySpan<byte>(srcPtrs[0], checked((int)(srcEndPtrs[0] - srcPtrs[0])));
        var dstBitmap = new Span<byte>(dstPtr, dstLength);

        if (op == BitmapOperation.NOT)
        {
            TensorPrimitives.OnesComplement(srcBitmap, dstBitmap);
        }
        else
        {
            srcBitmap.CopyTo(dstBitmap);
        }
    }

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Ensure at least two DIFF source keys exist before issuing the command (EXISTS src1 src2).
  2. If operating on possibly-absent keys, pre-populate the missing sources (e.g., empty bitmaps) or choose a different op.
  3. Handle the error at the client and retry once the second source is present.

Example fix

# before
BITOP DIFF dest src1 src2   # only src1 exists -> error
# after
SET src2 ""                 # ensure the second source exists (empty bitmap)
BITOP DIFF dest src1 src2
Defensive patterns

Strategy: validation

Validate before calling

// Before BITOP DIFF, ensure >= 2 of the named source keys exist
if (op == "DIFF") {
    var existing = await client.ExistsAsync(srcKeys);
    if (existing < 2) return BadRequest("BITOP DIFF needs at least two existing source bitmaps");
}

Try / catch

catch (GarnetException ex) when (ex.Message == "BITOP DIFF operation requires at least two source bitmaps") {
    // One or more DIFF source keys were missing; create them or pick another op
    logger.LogWarning("BITOP DIFF had too few existing sources");
    return RetryOrCreateSources();
}

Prevention

When it happens

Trigger: Client sends 'BITOP DIFF dest src1 src2' where only src1 (or only src2) exists in the database; the storage layer resolves just one source bitmap and calls InvokeBitOperationUnsafe with srcCount == 1.

Common situations: Running DIFF against keys where one source was never written or has expired; a race where a source key is deleted between the arg-count check and resolution.

Related errors


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