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

  1. Validate/coerce the value before it reaches the template (parse to a number in code, defaulting when empty)
  2. Ensure the String is a plain number parseable by new BigDecimal(...), e.g. '1.5' not '1,5' or ''
  3. If empty means false, guard the condition: {#if myParam?? && myParam != '' && myParam > 5}
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/0043887a1365d89b. Report an issue: GitHub.