{"record":{"id":"98013a410a6f54ea","repo":"elastic/elasticsearch","slug":"fullval-cannot-be-converted-to-clazz-getsimpl","errorCode":null,"errorMessage":"${fullVal} cannot be converted to ${clazz.getSimpleName()} without data loss","messagePattern":"(.+?) cannot be converted to (.+?) without data loss","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java","lineNumber":81,"sourceCode":"        this.restApiVersion = restApiVersion;\n    }\n\n    public AbstractXContentParser(NamedXContentRegistry xContentRegistry, DeprecationHandler deprecationHandler) {\n        this(xContentRegistry, deprecationHandler, RestApiVersion.current());\n    }\n\n    // The 3rd party parsers we rely on are known to silently truncate fractions: see\n    // http://fasterxml.github.io/jackson-core/javadoc/2.3.0/com/fasterxml/jackson/core/JsonParser.html#getShortValue()\n    // If this behaviour is flagged as undesirable and any truncation occurs\n    // then this method is called to trigger the\"malformed\" handling logic\n    void ensureNumberConversion(boolean coerce, long result, Class<? extends Number> clazz) throws IOException {\n        if (coerce == false) {\n            double fullVal = doDoubleValue();\n            if (result != fullVal) {\n                // Need to throw type IllegalArgumentException as current catch\n                // logic in NumberFieldMapper.parseCreateField relies on this\n                // for \"malformed\" value detection\n                throw new IllegalArgumentException(fullVal + \" cannot be converted to \" + clazz.getSimpleName() + \" without data loss\");\n            }\n        }\n    }\n\n    @Override\n    public boolean isBooleanValue() throws IOException {\n        return switch (currentToken()) {\n            case VALUE_BOOLEAN -> true;\n            case VALUE_STRING -> {\n                if (hasTextCharacters()) {\n                    yield Booleans.isBoolean(textCharacters(), textOffset(), textLength());\n                } else {\n                    yield Booleans.isBoolean(text());\n                }\n            }\n            default -> false;\n        };\n    }","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java#L63-L99","documentation":"Thrown by AbstractXContentParser.ensureNumberConversion() when coerce is false and a narrowing conversion from double to the target integer type would lose fractional data. The method compares the double value (fullVal) with the already-narrowed result; if they differ, the original value had a fractional part that would be silently truncated.","triggerScenarios":"A numeric field with coerce=false receiving a value like 42.5 for an integer or long field. The parser reads the value as a double internally, narrows it to long/int/short, and then detects that the double had a fractional part that was dropped. With coerce=true this truncation is allowed; with coerce=false it is rejected.","commonSituations":"Indexing a float/double value into an integer field mapping with coerce disabled. Client sending 3.14 where the mapping expects a long. Aggregation or script producing fractional results written to integer fields.","solutions":["Round or truncate the value before sending if integer storage is intended.","Change the field mapping type from integer/long to float/double if fractional values are expected.","Enable coerce in the mapping to accept silent truncation of fractional parts.","Validate numeric values client-side to ensure they have no fractional component for integer fields."],"exampleFix":"// before — fractional value into integer field with coerce=false\n{ \"quantity\": 42.5 }\n\n// after — integer value\n{ \"quantity\": 42 }","handlingStrategy":"validation","validationCode":"// Before indexing into integer fields, verify no fractional part if coerce is disabled\npublic static void validateNoFractionalLoss(Object value, String fieldName) {\n    if (value instanceof Number n && n.doubleValue() != Math.floor(n.doubleValue())) {\n        throw new IllegalArgumentException(\n            fieldName + \" has fractional part \" + n + \" that would be lost in integer conversion\"\n        );\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    parser.intValue(false);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"cannot be converted to\") && e.getMessage().contains(\"without data loss\")) {\n        throw new BadRequestException(\"Fractional value cannot be stored in integer field: \" + e.getMessage());\n    }\n    throw e;\n}","preventionTips":["Ensure fractional values are only sent to float/double fields, not integer/long fields.","Enable coerce in the mapping if silent truncation of fractional parts is acceptable.","Round values to integers client-side before sending to integer-mapped fields."],"tags":["parsing","xcontent","coercion","numeric","data-loss","type-mismatch"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}