flowable/flowable-engine · error · ELException
error.coerce.value
error.coerce.value
Error message
error.coerce.value
What it means
Thrown when a String value cannot be parsed as a BigDecimal during EL coercion in TypeConverterImpl.coerceToBigDecimal. The code catches NumberFormatException from new BigDecimal(String) and rethrows it as ELException with code error.coerce.value. Unlike error.coerce.type, the type was correct but the value's content was invalid.
Solutions
- Sanitize the string before it reaches EL: strip currency symbols, grouping separators, and whitespace.
- Normalize to the expected decimal format: replace ',' with '.' for decimal separators and remove thousands separators.
- Parse/validate with new BigDecimal(str) in a try-catch in your own code before evaluating the expression.
- Fix the source data so numeric fields contain only valid numeric text.
Example fix
// before
String amount = "€1,234.56"; // used in ${amount * 2}
// after
String amount = new BigDecimal("1,234.56".replace("€","").replace(",","")).toString(); // "1234.56" Defensive patterns
Strategy: validation
Validate before calling
try { new java.math.BigDecimal(str.trim().replace(",", "")); return true; } catch (NumberFormatException e) { return false; } Type guard
static boolean isBigDecimalParsable(String s) { try { new java.math.BigDecimal(s.trim()); return true; } catch (Exception e) { return false; } } Try / catch
try { Object r = expression.getValue(context); } catch (jakarta.el.ELException e) { if (e.getCause() instanceof NumberFormatException nfe) { log.error("Invalid numeric string: {}", nfe.getMessage()); } } Prevention
- Normalize locale-formatted numbers before EL evaluation.
- Strip currency symbols, spaces, and grouping separators from input.
- Validate numeric strings with BigDecimal parse before binding.
- Store numeric values as numbers, not formatted strings.
When it happens
Trigger: An EL expression produces a String like "12.3abc", "", locale-formatted numbers ("1,234.56" with grouped separators or comma decimals), currency symbols, or trailing whitespace where a BigDecimal operand is required (arithmetic, comparisons, numeric assignment).
Common situations: User-supplied input bound into EL variables; locale differences (German "1.234,56" parsed as "1.234"); currency/percentage strings from forms; whitespace or non-breaking spaces from spreadsheets.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Cannot parse EL property
- error.coerce.type
- Builder is missing constructor (can't pass features)
- Cannot change fixed value with
- Cannot coerce property to array index:
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/e60d77614b542b8c.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/misc/TypeConverterImpl.java:88
protected BigDecimal coerceToBigDecimal(Object value) {
if (value == null || "".equals(value)) {
return BigDecimal.valueOf(0L);
}
if (value instanceof BigDecimal) {
return (BigDecimal)value;
}
if (value instanceof BigInteger) {
return new BigDecimal((BigInteger)value);
}
if (value instanceof Number) {
return new BigDecimal(((Number)value).doubleValue());
}
if (value instanceof String) {
try {
return new BigDecimal((String)value);
} catch (NumberFormatException e) {
throw new ELException(LocalMessages.get("error.coerce.value", value, value.getClass(), BigDecimal.class), e);
}
}
if (value instanceof Character) {
return new BigDecimal((short)((Character)value).charValue());
}
if (value instanceof LambdaExpression lambdaExpression) {
return coerceToBigDecimal(resolveLambdaExpression(lambdaExpression));
}
throw new ELException(LocalMessages.get("error.coerce.type", value, value.getClass(), BigDecimal.class));
}
protected BigInteger coerceToBigInteger(Object value) {
if (value == null || "".equals(value)) {
return BigInteger.valueOf(0L);
}
if (value instanceof BigInteger) {
return (BigInteger)value;
}View on GitHub (pinned to d6d39ce1c6)