{"record":{"id":"e7be45d34ee13b73","repo":"elastic/elasticsearch","slug":"value-stringvalue-is-out-of-range-for-a-long","errorCode":null,"errorMessage":"Value [${stringValue}] is out of range for a long","messagePattern":"Value \\[(.+?)\\] is out of range for a long","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java","lineNumber":224,"sourceCode":"     * that way (decimals, scientific notation, big integers) fall back to {@link java.math.BigDecimal}.\n     * A fractional part is truncated when {@code coerce=true} and rejected with\n     * {@link IllegalArgumentException} when {@code coerce=false}. Values outside\n     * [{@link Long#MIN_VALUE}, {@link Long#MAX_VALUE}] always throw.\n     */\n    public static long toLong(String stringValue, boolean coerce) {\n        try {\n            return Long.parseLong(stringValue);\n        } catch (NumberFormatException e) {\n            // we will try again with BigDecimal\n        }\n\n        final BigInteger bigIntegerValue;\n        try {\n            final BigDecimal bigDecimalValue = new BigDecimal(stringValue);\n            // long can have a maximum of 19 digits - any more than that cannot be a long\n            // the scale is stored as the negation, so negative scale -> big number\n            if (bigDecimalValue.scale() < -19) {\n                throw new IllegalArgumentException(\"Value [\" + stringValue + \"] is out of range for a long\");\n            }\n            // large scale -> very small number\n            if (bigDecimalValue.scale() > 19) {\n                if (coerce) {\n                    bigIntegerValue = BigInteger.ZERO;\n                } else {\n                    throw new ArithmeticException(\"Number has a decimal part\");\n                }\n            } else {\n                bigIntegerValue = coerce ? bigDecimalValue.toBigInteger() : bigDecimalValue.toBigIntegerExact();\n            }\n        } catch (ArithmeticException e) {\n            throw new IllegalArgumentException(\"Value [\" + stringValue + \"] has a decimal part\");\n        } catch (NumberFormatException e) {\n            throw new IllegalArgumentException(\"For input string: \\\"\" + stringValue + \"\\\"\");\n        }\n\n        if (bigIntegerValue.compareTo(LONG_MAX_VALUE_AS_BIGINTEGER) > 0 || bigIntegerValue.compareTo(LONG_MIN_VALUE_AS_BIGINTEGER) < 0) {","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java#L206-L242","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)."],"exampleFix":"// before: field mapped as long, value \"12345678901234567890123\"\nPUT /idx/_mapping { \"properties\": { \"id\": { \"type\": \"long\" } } }\n// after: use keyword for oversized numeric IDs\nPUT /idx/_mapping { \"properties\": { \"id\": { \"type\": \"keyword\" } } }","handlingStrategy":"validation","validationCode":"static boolean isParsableLong(String s) {\n  if (s == null) return false;\n  try {\n    new java.math.BigDecimal(s);\n  } catch (NumberFormatException e) { return false; }\n  // reject values with more than 19 integer digits up front\n  int dot = s.indexOf('.');\n  String intPart = dot < 0 ? s : s.substring(0, dot);\n  int digits = intPart.replaceAll(\"[^0-9]\", \"\").length();\n  return digits <= 19;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["xcontent","parsing","numeric","long","mapping"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}