elastic/elasticsearch · error · IllegalArgumentException

Value [${stringValue}] is out of range for a long

Error message

Value [${stringValue}] is out of range for a long

What it means

Thrown by AbstractXContentParser.toLong(String, boolean) when a numeric string's BigDecimal scale is less than -19, meaning the integer portion has more than 19 digits and cannot possibly fit in a signed 64-bit long. This is a fast-fail short-circuit issued before any BigInteger range comparison. It signals the value is structurally too large to be a long regardless of magnitude checks.

Source

Thrown at libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java:224

     * that way (decimals, scientific notation, big integers) fall back to {@link java.math.BigDecimal}.
     * A fractional part is truncated when {@code coerce=true} and rejected with
     * {@link IllegalArgumentException} when {@code coerce=false}. Values outside
     * [{@link Long#MIN_VALUE}, {@link Long#MAX_VALUE}] always throw.
     */
    public static long toLong(String stringValue, boolean coerce) {
        try {
            return Long.parseLong(stringValue);
        } catch (NumberFormatException e) {
            // we will try again with BigDecimal
        }

        final BigInteger bigIntegerValue;
        try {
            final BigDecimal bigDecimalValue = new BigDecimal(stringValue);
            // long can have a maximum of 19 digits - any more than that cannot be a long
            // the scale is stored as the negation, so negative scale -> big number
            if (bigDecimalValue.scale() < -19) {
                throw new IllegalArgumentException("Value [" + stringValue + "] is out of range for a long");
            }
            // large scale -> very small number
            if (bigDecimalValue.scale() > 19) {
                if (coerce) {
                    bigIntegerValue = BigInteger.ZERO;
                } else {
                    throw new ArithmeticException("Number has a decimal part");
                }
            } else {
                bigIntegerValue = coerce ? bigDecimalValue.toBigInteger() : bigDecimalValue.toBigIntegerExact();
            }
        } catch (ArithmeticException e) {
            throw new IllegalArgumentException("Value [" + stringValue + "] has a decimal part");
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("For input string: \"" + stringValue + "\"");
        }

        if (bigIntegerValue.compareTo(LONG_MAX_VALUE_AS_BIGINTEGER) > 0 || bigIntegerValue.compareTo(LONG_MIN_VALUE_AS_BIGINTEGER) < 0) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Re-map the field to a type that can hold the value: use `keyword` for IDs, `double`/`scaled_float` for large numerics, or keep the value as a string.
  2. Sanitize incoming values at ingest time to clamp or reject numbers exceeding Long.MAX_VALUE (9223372036854775807) before they reach the parser.
  3. If the value is legitimately huge and you need range queries, store it as `keyword` and use term/range queries on the string form, or split into multiple fields.
  4. Verify the upstream producer is not corrupting the field (e.g. concatenating two longs, encoding errors).

Example fix

// before: field mapped as long, value "12345678901234567890123"
PUT /idx/_mapping { "properties": { "id": { "type": "long" } } }
// after: use keyword for oversized numeric IDs
PUT /idx/_mapping { "properties": { "id": { "type": "keyword" } } }
Defensive patterns

Strategy: validation

Validate before calling

static boolean isParsableLong(String s) {
  if (s == null) return false;
  try {
    new java.math.BigDecimal(s);
  } catch (NumberFormatException e) { return false; }
  // reject values with more than 19 integer digits up front
  int dot = s.indexOf('.');
  String intPart = dot < 0 ? s : s.substring(0, dot);
  int digits = intPart.replaceAll("[^0-9]", "").length();
  return digits <= 19;
}

Prevention

When it happens

Trigger: Calling longValue()/longValue(coerce) or the static toLong(string, coerce) on an XContentParser positioned on a VALUE_STRING token whose text has more than 19 digits before the decimal point (e.g. "12345678901234567890123"). Also reached when document mapping forces a long field and the indexed/supplied value overflows 19 integer digits, including scientific notation like "1e30" (scale -29).

Common situations: Indexing IDs, timestamps with nanosecond precision, or numeric strings produced by upstream systems (BigInteger serializations, UUID-as-number, bank/account numbers) into a field mapped as long. Bulk-indexing pipelines that pass through numeric values without range validation. Migrating data with wider numeric types into a long-mapped field.

Related errors


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