quarkusio/quarkus · error · TemplateException
Cannot coerce to a BigDecimal
Error message
Cannot coerce to a BigDecimal
What it means
When an {if} section needs numeric comparison (e.g. {if a > 1.5}), Qute coerces operand values to BigDecimal. Coercion supports Number types, BigDecimal/BigInteger and exact numeric Strings. If a value cannot be represented as a BigDecimal — typically an empty or non-numeric string — TemplateException is thrown at template evaluation time.
Source
Thrown at independent-projects/qute/core/src/main/java/io/quarkus/qute/IfSectionHelper.java:583
}
static BigDecimal getDecimal(Object value) {
if (value instanceof BigDecimal decimal) {
return decimal;
} else if (value instanceof BigInteger bigInteger) {
return new BigDecimal(bigInteger);
} else if (value instanceof Integer integer) {
return BigDecimal.valueOf(integer);
} else if (value instanceof Long _long) {
return BigDecimal.valueOf(_long);
} else if (value instanceof Double _double) {
return BigDecimal.valueOf(_double);
} else if (value instanceof Float _float) {
return BigDecimal.valueOf(_float);
} else if (value instanceof String string) {
return new BigDecimal(string);
}
throw new TemplateException("Cannot coerce " + value + " to a BigDecimal");
}
}
static <B extends ErrorInitializer & WithOrigin> List<Object> parseParams(List<Object> params, B block) {
replaceOperatorsAndCompositeParams(params, block);
int highestPrecedence = getHighestPrecedence(params);
if (!isGroupingNeeded(params)) {
// No operators or all of the same precedence
return params;
}
// Take the operators with highest precedence and form groups
// For example "user.active && target.status == NEW && !target.voted" becomes "user.active && [target.status == NEW] && [!target.voted]"
// The algorithm used is not very robust and should be improved later
List<Object> highestGroup = null;View on GitHub (pinned to e1c734241f)
Solutions
- Validate/coerce the value before it reaches the template (parse to a number in code, defaulting when empty)
- Ensure the String is a plain number parseable by new BigDecimal(...), e.g. '1.5' not '1,5' or ''
- If empty means false, guard the condition: {#if myParam?? && myParam != '' && myParam > 5}
- Compare against a string/number of the same type to avoid coercion, or pass a Number (Integer/Double) instead of String
Example fix
// before: template {#if count > 5} with count = "" (String)
// after: pass a parsed Number with a default
int parsed = raw == null || raw.isBlank() ? 0 : Integer.parseInt(raw);
data.put("count", parsed); Defensive patterns
Strategy: validation
Validate before calling
String s = maybeNull == null ? "" : maybeNull.trim(); boolean ok = !s.isEmpty() && new BigDecimal(s) is parseable; // wrap in try/catch NumberFormatException
Type guard
boolean isNumeric(String v) {
if (v == null || v.isBlank()) return false;
try { new java.math.BigDecimal(v.trim()); return true; }
catch (NumberFormatException e) { return false;
} } Try / catch
try {
template.render(data);
} catch (TemplateException e) {
if (e.getMessage().contains("Cannot coerce")) {
log.error("Non-numeric value used in {#if} comparison: " + e.getMessage());
}
throw e;
} Prevention
- Validate/coerce request parameters to Numbers before putting them into template data
- Never pass empty Strings into numeric template comparisons
- Use dot-decimal formats only ('1.5', not '1,5')
- Use Qute value resolvers/converters to normalize values
When it happens
Trigger: Comparing a String value in an if-condition where the string is empty (note the message shows two spaces: value renders empty) or not parseable by java.math.BigDecimal, e.g. {if 'abc' > 1} or {if myParam > 5} where myParam is an empty form/query parameter.
Common situations: Empty HTTP request parameters or missing form fields bound to Strings used in numeric template comparisons; locale-formatted numbers like '1,5' or '12.0.1'; whitespace-only strings; config properties left blank.
Related errors
- Invalid template link [${templateLink}] - Expeting a link th
- Templates that are not backed by a file must provide extensi
- Literal must not be null
- Expression is not a literal:
- Engine not set
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/0043887a1365d89b.
Report an issue: GitHub.