elastic/elasticsearch · error · IllegalArgumentException
Value [${stringValue}] has a decimal part
Error message
Value [${stringValue}] has a decimal part What it means
Thrown by AbstractXContentParser.toLong when coerce=false and the parsed BigDecimal has a fractional part that cannot be losslessly converted to an integer. The ArithmeticException from toBigIntegerExact() (or the explicit scale>19 branch) is caught and re-thrown as this IllegalArgumentException. It enforces strict (non-coercing) long parsing semantics.
Source
Thrown at libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java:237
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) {
throw new IllegalArgumentException("Value [" + stringValue + "] is out of range for a long");
}
assert bigIntegerValue.longValueExact() <= Long.MAX_VALUE; // asserting that no ArithmeticException is thrown
return bigIntegerValue.longValue();
}
@Override
public long longValue() throws IOException {
return longValue(DEFAULT_NUMBER_COERCE_POLICY);
}
@OverrideView on GitHub (pinned to db6a809a66)
Solutions
- Enable coercion on the field mapping: set "coerce": true so fractional parts are truncated toward zero.
- Fix the producer to emit integer values (round/truncate before sending).
- Change the field type to double/scaled_float if fractional precision is genuinely needed.
- If reading manually via the parser, call longValue(true) to allow truncation.
Example fix
// before: strict long field rejects "12.99"
PUT /idx/_mapping { "properties": { "qty": { "type": "long", "coerce": false } } }
// after: allow truncation
PUT /idx/_mapping { "properties": { "qty": { "type": "long", "coerce": true } } } Defensive patterns
Strategy: validation
Validate before calling
static boolean isStrictLong(String s) {
if (s == null) return false;
try { Long.parseLong(s); return true; }
catch (NumberFormatException e) { return false; }
} Try / catch
try { parser.longValue(false); }
catch (IllegalArgumentException e) {
if (e.getMessage().contains("decimal part")) { /* coerce or reject */ }
else throw e;
} Prevention
- Either enable coerce on long fields or guarantee integer-only producers.
- Use longValue(true) when truncation is acceptable.
- Round/truncate decimal sources before indexing into long fields.
When it happens
Trigger: Parsing a string like "1.5", "3.14", or "0.001" into a long with coerce=false (the strict policy). Reached via longValue(false) on a VALUE_STRING token, or when a long-mapped field receives a decimal value and the index-time coerce setting is disabled.
Common situations: Mappings with "coerce": false on a long field receiving float input. Reading JSON where a numeric field is serialized with a decimal point by a producer that treats all numbers as doubles. ES|QL or runtime field evaluation casting decimal strings to long without coercion.
Related errors
- Value [${stringValue}] is out of range for a long
- 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/4210545cd9855d5f.
Report an issue: GitHub.