quarkusio/quarkus · error · IllegalArgumentException

Unexpected tag: " + tag

Error message

Unexpected tag: " + tag

What it means

Thrown by Qute's Parser.flushTag when a template tag's type does not match any known tag kind (PARAM, EXPRESSION, section, comment, CDATA, etc.). It indicates an internal parser inconsistency rather than invalid template syntax, since the lexer normally assigns a valid Tag enum to every token.

Source

Thrown at independent-projects/qute/core/src/main/java/io/quarkus/qute/Parser.java:463

    private void flushTag() {
        state = State.TEXT;
        String content = buffer.toString().trim();
        String tagStr = START_DELIMITER + content + END_DELIMITER;

        Tag tag = Tag.from(content.charAt(0), config.expressionCommand());
        switch (tag) {
            // a section/block start; {#if}, {#else}, etc.
            case SECTION -> sectionStart(content, tagStr);
            // a section/block end
            case SECTION_END -> sectionEnd(content, tagStr);
            // parameter declaration; {@org.acme.Foo foo}
            case PARAM -> parameterDeclaration(content, tagStr);
            case EXPRESSION -> sectionStack.peek()
                    .currentBlock()
                    .addNode(new ExpressionNode(
                            createExpression(config.expressionCommand() != null ? content.substring(1) : content),
                            engine));
            default -> throw new IllegalArgumentException("Unexpected tag: " + tag);
        }
        this.buffer = new StringBuilder();
    }

    private void sectionStart(String content, String tag) {
        boolean isEmptySection = false;
        if (content.charAt(content.length() - 1) == Tag.SECTION_END.command) {
            content = content.substring(0, content.length() - 1);
            isEmptySection = true;
        }

        Iterator<String> iter = splitSectionParams(content, this);
        if (!iter.hasNext()) {
            throw error(ParserError.NO_SECTION_NAME, "no section name declared for {tag}").argument("tag", tag).build();
        }
        String sectionName = iter.next();
        sectionName = sectionName.substring(1, sectionName.length());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Inspect your ParserHook / custom tag implementations and ensure they only emit known Parser.Tag values or register handling for new ones.
  2. Check the template content near the reported position for unusual characters custom code may have transformed into an unknown tag.
  3. Update the Quarkus/Qute extension version consistently with any custom parsing code to align tag enums.
  4. If reproducible with vanilla templates, file a Qute issue with the template snippet — it indicates a lexer/parser bug.

Example fix

// before (custom parser hook emitting an unmapped tag)
builder.addParserHook(parser -> parser.addTag("$custom", myTag));

// after (use only supported Tag values, e.g. SECTION for custom sections)
builder.addParserHook(parser -> parser.addTag("$custom", Parser.Tag.SECTION));
Defensive patterns

Strategy: try-catch

Try / catch

try {
    engine.parse(templateContent);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unexpected tag:")) {
        // audit custom ParserHooks / report parser bug with template snippet
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A Tag value reaches Parser.flushTag() that is not handled in the switch — typically caused by adding a custom Parser.Tag via EngineBuilder.addParserHook/custom parser hooks, or by a parser/lexer bug where a delimiter character produced an unmapped tag type.

Common situations: Developers writing custom Qute parser hooks that emit custom tags the core flushTag switch doesn't handle; upgrading Qute versions where tag handling changed and copied parser-hook code is out of sync; syntax-highlighting/preprocessing tools injecting malformed tag tokens.

Related errors


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