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
- 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.
- Sanitize incoming values at ingest time to clamp or reject numbers exceeding Long.MAX_VALUE (9223372036854775807) before they reach the parser.
- 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.
- 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
- Validate numeric strings against Long range before indexing into long-mapped fields.
- Map oversized numeric identifiers as keyword, not long.
- Audit ingest pipelines for unbounded numeric magnitudes.
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
- Value [${stringValue}] has a decimal part
- For input string: "${stringValue}"
- ${clazz.getSimpleName()} value passed as String
- ${fullVal} cannot be converted to ${clazz.getSimpleName()} w
- Value [${text}] is out of range for a short
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/e7be45d34ee13b73.
Report an issue: GitHub.