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
- Change the parameter type to java.lang.Object and cast inside the method body
- 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
- Always declare @TemplateAttribute params as Object and cast inside
- Keep a shared utility for safe attribute extraction
- Add signature tests for extension methods using attributes
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
- Template extension method declared on must be static:
- Template extension method declared on must not return void:
- Template extension method declared on must not be private:
- A template extension method matching multiple names or a reg
- Template extension method declared on must accept at least
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/a59bc0ed352993f6.
Report an issue: GitHub.