elastic/elasticsearch · error · IllegalArgumentException

[bitmap_terms] query expects a base64-encoded RoaringBitmap…

Error message

[bitmap_terms] query expects a base64-encoded RoaringBitmap value

What it means

Thrown when the value string is not valid base64. The query first base64-decodes the value; if java.util.Base64.getDecoder().decode throws IllegalArgumentException (illegal character, wrong padding, etc.) it is wrapped in this IllegalArgumentException pointing at the encoding step.

Solutions

  1. Encode the serialized bitmap bytes with standard base64 (java.util.Base64.getEncoder() or Python base64.standard_b64encode).
  2. Strip whitespace/newlines and any data-URL prefix before sending.
  3. If using base64url, translate -_ to +/ and trim padding as needed.

Example fix

// before (hex string)
{"bitmap_terms":{"field":"uid","value":"030100"}}
// after (base64 of the serialized bitmap)
{"bitmap_terms":{"field":"uid","value":"AwABAQ=="}}
Defensive patterns

Strategy: validation

Validate before calling

// Validate base64 (standard alphabet) before sending.
const RE = /^[A-Za-z0-9+/]*={0,2}$/;
function assertBase64(v) {
  if (!v || !RE.test(v) || v.length % 4 !== 0) {
    throw new Error("value is not valid standard base64");
  }
}

Prevention

When it happens

Trigger: Passing a hex-encoded bitmap instead of base64; passing a data-URL prefix like "data:...;base64,..."; base64 with URL-safe characters (-_) when standard decoder is used; corrupted/whitespace-padded string; empty string.

Common situations: Client library encodes with base64url without translating to standard base64; copy-paste truncation; reading the bitmap from a text channel that strips/replaces characters.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/4c29c33f28d31fe6. Report an issue: GitHub.

Appendix: source

Thrown at modules/bitmap/src/main/java/org/elasticsearch/index/query/bitmapterms/BitmapTermsQueryBuilder.java:166

    @Override
    protected Query doToQuery(SearchExecutionContext context) throws IOException {
        MappedFieldType fieldType = context.getFieldType(fieldName);
        if (!(fieldType instanceof NumberFieldMapper.NumberFieldType numberFieldType)
            || (numberFieldType.numberType() != NumberFieldMapper.NumberType.INTEGER
                && numberFieldType.numberType() != NumberFieldMapper.NumberType.LONG)
            || (numberFieldType.isIndexedWithPoints() == false && numberFieldType.isIndexedWithTerms() == false)) {
            throw new IllegalArgumentException(
                "[bitmap_terms] query is not supported on field ["
                    + fieldName
                    + "]: only supported on [integer] and [long] fields indexed with points or terms"
            );
        }
        byte[] bitmapBytes;
        try {
            bitmapBytes = Base64.getDecoder().decode(value);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("[bitmap_terms] query expects a base64-encoded RoaringBitmap value", e);
        }
        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);

View on GitHub (pinned to db6a809a66)