elastic/elasticsearch · error · IllegalArgumentException
[bitmap_terms] query value is not a valid serialized Roaring
Error message
[bitmap_terms] query value is not a valid serialized RoaringBitmap
What it means
Thrown by integerValues when IntBitmap.deserialize fails on the decoded bytes. The bytes were valid base64 but do not form a valid serialized 32-bit RoaringBitmap (wrong cookie/header, truncated, or a 64-bit portable-format payload supplied to an integer field).
Source
Thrown at modules/bitmap/src/main/java/org/elasticsearch/index/query/bitmapterms/BitmapTermsQueryBuilder.java:186
BitmapValues values = switch (numberFieldType.numberType()) {
case INTEGER -> integerValues(bitmapBytes);
case LONG -> longValues(bitmapBytes);
default -> throw new AssertionError("unexpected number type [" + numberFieldType.numberType() + "]");
};
// The two queries differ only in which index structure they merge against; the field's width
// is carried by the BitmapValues.
if (numberFieldType.isIndexedWithTerms()) {
return new BitmapTermsQuery(fieldName, values);
}
return new BitmapBKDQuery(fieldName, values);
}
private static IntBitmap integerValues(byte[] bitmapBytes) {
IntBitmap bitmap;
try {
bitmap = IntBitmap.deserialize(bitmapBytes);
} catch (Exception e) {
throw new IllegalArgumentException("[bitmap_terms] query value is not a valid serialized RoaringBitmap", e);
}
if (bitmap.hasNegativeValues()) {
throw new IllegalArgumentException(
"[bitmap_terms] query on [integer] field only supports non-negative values (0 to 2147483647)"
);
}
return bitmap;
}
private static LongBitmap longValues(byte[] bitmapBytes) {
LongBitmap bitmap;
try {
bitmap = LongBitmap.deserializePortable(bitmapBytes);
} catch (Exception e) {
throw new IllegalArgumentException(
"[bitmap_terms] query value is not a valid serialized 64-bit RoaringBitmap in the portable format",
e
);View on GitHub (pinned to db6a809a66)
Solutions
- For integer fields, serialize with 32-bit RoaringBitmap.serialize (java) or pyroaching BitMap.serialize, then base64-encode.
- Do not feed a 64-bit/portable-format payload to an integer field; use a long field for 64-bit bitmaps.
- Verify the byte length and cookie header match the 32-bit roaring format before sending.
Example fix
// before: 64-bit portable bytes sent to integer field bitmap = Roaring64NavigableMap(); bitmap.add(...); value = base64(bitmap.serializePortable()) // after: 32-bit bitmap for integer field bitmap = RoaringBitmap(); bitmap.add(...); value = base64(bitmap.serialize())
Defensive patterns
Strategy: validation
Validate before calling
// Round-trip the bitmap on the client to ensure it deserializes before sending.
import org.roaringbitmap.RoaringBitmap;
byte[] bytes = ...; // your serialized 32-bit bitmap
RoaringBitmap r = RoaringBitmap.deserialize(ByteBuffer.wrap(bytes));
if (r.hasNegativeValuesRunningLengthIntervals()) throw new IllegalArgumentException("invalid");
String value = Base64.getEncoder().encodeToString(bytes); Prevention
- For integer fields always use the 32-bit RoaringBitmap.serialize output.
- Round-trip deserialize locally before sending to catch format mismatches early.
When it happens
Trigger: Supplying a Roaring64NavigableMap.serializePortable payload to an integer field; supplying a portable vs run-length-laid-out 32-bit bitmap that the deserializer rejects; truncated bytes from a wrong encoder. Note the integer path expects the format from RoaringBitmap.serialize / pyroaring BitMap.serialize.
Common situations: Reusing the same base64 blob across integer and long fields; client using the wrong Roaring serialization method; version skew between the Roaring library on the client and server.
Related errors
- [bitmap_terms] query value is not a valid serialized 64-bit
- [bitmap_terms] query on [integer] field only supports non-ne
- [bitmap_terms] query on [long] field only supports non-negat
- Empty
- Linear ring is not supported by WKB
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/cb19a176e70a6fa1.
Report an issue: GitHub.