{"record":{"id":"017fca2ccf719ead","repo":"hibernate/hibernate-orm","slug":"error-coercing-value","errorCode":null,"errorMessage":"Error coercing value","messagePattern":"Error coercing value","errorType":"exception","errorClass":"CoercionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java","lineNumber":400,"sourceCode":"\t}\n\n\tpublic static CoercionException coercionException(Exception e) {\n\t\tvar ce = new CoercionException( e.getMessage() );\n\t\tce.addSuppressed( e );\n\t\treturn ce;\n\t}\n\n\t@FunctionalInterface\n\tpublic interface Coercer<T> {\n\t\tT doCoercion();\n\t}\n\n\tpublic static <T> T coerceWrappingError(Coercer<T> coercer) {\n\t\ttry {\n\t\t\treturn coercer.doCoercion();\n\t\t}\n\t\tcatch (ArithmeticException | NumberFormatException e) {\n\t\t\tthrow new CoercionException( \"Error coercing value\", e );\n\t\t}\n\t}\n}\n","sourceCodeStart":382,"sourceCodeEnd":404,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java#L382-L404","documentation":"CoercionHelper.coerceWrappingError runs an 'exact' conversion (BigDecimal.toBigIntegerExact, exact narrowing ops, numeric string parsing) and rethrows any ArithmeticException or NumberFormatException as a CoercionException with the generic message 'Error coercing value', keeping the original exception as the cause. It exists so Hibernate surfaces one exception type across all coercions; the actual reason is always in getCause().","triggerScenarios":"toBigInteger on a fractional BigDecimal such as new BigDecimal(\"1.5\") (toBigIntegerExact throws ArithmeticException 'Rounding necessary'); coercing an unparseable numeric string ('12abc', '') through the numeric helpers; exact BigInteger/BigDecimal narrowing where the value overflows the target type.","commonSituations":"External input arriving as strings or BigDecimals and bound to integer-typed attributes; CSV/ETL loads; converters that assumed input was already integral.","solutions":["Inspect e.getCause(): ArithmeticException means fractional or overflowing value, NumberFormatException means unparseable string","Validate and normalize inputs before binding (setScale with an explicit RoundingMode, pre-parse strings)","For BigDecimal sources, decide a policy: reject, or setScale(0, RoundingMode.HALF_UP) before converting","Catch CoercionException at the API boundary and turn it into a user-facing validation message"],"exampleFix":"// before\nBigInteger b = new BigDecimal(\"1.5\").toBigIntegerExact(); // ArithmeticException, wrapped by Hibernate\n\n// after\nBigInteger b = new BigDecimal(\"1.5\").setScale(0, RoundingMode.HALF_UP).toBigIntegerExact();","handlingStrategy":"try-catch","validationCode":"static BigDecimal validated(String raw) {\n    if (raw == null || !raw.matches(\"[+-]?[0-9]+(\\\\.[0-9]+)?\")) {\n        throw new IllegalArgumentException(\"not a number: \" + raw);\n    }\n    return new BigDecimal(raw);\n}","typeGuard":null,"tryCatchPattern":"try {\n    return CoercionHelper.toBigInteger(bigDecimalValue);\n} catch (CoercionException e) {\n    Throwable cause = e.getCause();\n    // ArithmeticException -> fractional/overflow; NumberFormatException -> bad string\n    throw new IllegalArgumentException(\"value not coercible: \" + cause, e);\n}","preventionTips":["Never feed raw external strings into numeric attributes","Decide an explicit rounding policy instead of relying on *Exact conversions","Log the cause, not just the message, for coercion failures"],"tags":["hibernate","type-coercion","numeric","wrapped-exception"],"backgroundTag":"numeric-type-coercion-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}