quarkusio/quarkus · error · TemplateException

Invalid composite parameter found:

Error message

Invalid composite parameter found: 

What it means

Qute parses composite (parenthesized) parameters inside {#if} sections, e.g. {#if (a || b) && c}. A composite param string starts with Parser.BEGIN_COMPOSITE_PARAM ('(') and must end with END_COMPOSITE_PARAM (')'). If the string ends with anything else, the parameter is structurally malformed and TemplateException is thrown during template parsing.

Source

Thrown at independent-projects/qute/core/src/main/java/io/quarkus/qute/IfSectionHelper.java:716

    }

    private static int getHighestPrecedence(List<Object> params) {
        int highestPrecedence = 0;
        for (Object param : params) {
            if (param instanceof Operator) {
                Operator op = (Operator) param;
                if (op.precedence > highestPrecedence) {
                    highestPrecedence = op.precedence;
                }
            }
        }
        return highestPrecedence;
    }

    static <B extends ErrorInitializer & WithOrigin> List<Object> processCompositeParam(String stringParam, B block) {
        // Composite params
        if (!stringParam.endsWith("" + Parser.END_COMPOSITE_PARAM)) {
            throw new TemplateException("Invalid composite parameter found: " + stringParam);
        }
        List<Object> split = new ArrayList<>();
        Parser.splitSectionParams(stringParam.substring(1, stringParam.length() - 1),
                block)
                .forEachRemaining(split::add);
        return parseParams(split, block);
    }

    @SuppressWarnings("unchecked")
    static Condition createCondition(Object param, SectionBlock block, Operator operator, SectionInitContext context) {

        Condition condition;

        if (param instanceof String) {
            String stringParam = param.toString();
            boolean logicalComplement = stringParam.startsWith(LOGICAL_COMPLEMENT);
            if (logicalComplement) {
                stringParam = stringParam.substring(1);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Balance the parentheses in the {#if} condition so every '(' has a matching ')', e.g. {#if (a || b) && c}
  2. If the condition is complex, split it into nested {#if} sections instead of one deeply parenthesized expression
  3. Validate template syntax at build/startup (templates are parsed eagerly when possible) so the failure is caught before users hit the page

Example fix

// before
{#if (user.active || user.admin && debug}...{/if}
// after
{#if (user.active || user.admin) && debug}...{/if}
Defensive patterns

Strategy: validation

Validate before calling

long opens = expr.chars().filter(c -> c == '(').count();
long closes = expr.chars().filter(c -> c == ')').count();
if (opens != closes) throw new IllegalArgumentException("Unbalanced parentheses in: " + expr);

Try / catch

try {
    engine.parse(content);
} catch (TemplateException e) {
    if (e.getMessage().startsWith("Invalid composite parameter found")) {
        throw new TemplateSyntaxException(content, "Unbalanced parentheses in {#if} expression", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A parenthesized fragment inside an {#if} section whose closing parenthesis is missing or the param string is corrupted, e.g. {#if (a || b && c} — the leading '(' opens a composite param but there is no matching ')'.

Common situations: Hand-edited templates where a closing paren was deleted; nested conditions with miscounted parentheses; template copy/paste truncation.

Related errors


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