quarkusio/quarkus · error · TemplateException

Template extension method parameter annotated with @Template

Error message

Template extension method parameter annotated with @TemplateAttribute declared on  must be of type java.lang.Object: 

What it means

@TemplateAttribute parameters receive arbitrary attribute values from the template evaluation context, so they must be declared as java.lang.Object. A narrower declared type causes this TemplateException because the generated code cannot safely cast/assign the value.

Source

Thrown at independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java:1000

            this.params = params;

            if (isNameParameterRequired) {
                Param nameParam = getFirst(ParamKind.NAME);
                if (nameParam == null || !nameParam.type.name().equals(DotNames.STRING)) {
                    throw new TemplateException(
                            "Template extension method declared on " + method.declaringClass().name()
                                    + " must accept at least one string parameter to match the name: " + method);
                }
            }
            if (!hasNamespace && getFirst(ParamKind.BASE) == null) {
                throw new TemplateException(
                        "Template extension method declared on " + method.declaringClass().name()
                                + " must accept at least one parameter to match the base object: " + method);
            }

            for (Param param : params) {
                if (param.kind == ParamKind.ATTR && !param.type.name().equals(DotNames.OBJECT)) {
                    throw new TemplateException(
                            "Template extension method parameter annotated with @TemplateAttribute declared on "
                                    + method.declaringClass().name()
                                    + " must be of type java.lang.Object: " + method);
                }
            }
        }

        public List<Type> parameterTypes() {
            return params.stream().map(p -> p.type).toList();
        }

        public String[] parameterTypesAsStringArray() {
            String[] types = new String[params.size()];
            for (int i = 0; i < params.size(); i++) {
                types[i] = params.get(i).type.name().toString();
            }
            return types;
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the parameter type to java.lang.Object and cast inside the method body
  2. Remove @TemplateAttribute if the parameter should be a regular extension argument

Example fix

// before
@TemplateAttribute String locale
// after
@TemplateAttribute Object locale
// then inside: String loc = (String) locale;
Defensive patterns

Strategy: validation

Validate before calling

for (var p : m.getParameters())
    if (p.isAnnotationPresent(TemplateAttribute.class) && p.getType() != Object.class)
        throw new IllegalStateException("@TemplateAttribute param must be Object: " + p);

Prevention

When it happens

Trigger: Annotating a parameter of type String/Integer/etc. with @TemplateAttribute on a template extension method; caught in the generator constructor's param loop.

Common situations: Copy-pasting a @RequestAttribute/@TemplateAttribute pattern onto a typed parameter; trying to get type safety by narrowing the attribute parameter type.

Related errors


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