quarkusio/quarkus · error · java.lang.IllegalStateException
No template extension methods declared on <class>; a templat
Error message
No template extension methods declared on <class>; a template extension method must be static, non-private and must not return void
What it means
Thrown when a class is annotated with @TemplateExtension (on the class, no specific methods listed) but Qute finds no valid template extension methods inside it. A valid extension method must be static, non-private, and must not return void.
Source
Thrown at extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java:1849
// Filter out non-static, synthetic, private and void methods
continue;
}
if ((namespace == null || namespace.isEmpty()) && method.parameterTypes().isEmpty()) {
// Filter out methods with no params for non-namespace extensions
continue;
}
if (methods.containsKey(method)) {
// Skip methods annotated with @TemplateExtension - method-level annotation takes precedence
skippedMethodLevelAnnotation = true;
continue;
}
found.add(method);
LOGGER.debugf("Found template extension method %s declared on %s", method,
method.declaringClass().name());
}
if (found.isEmpty() && !skippedMethodLevelAnnotation) {
throw new IllegalStateException("No template extension methods declared on " + entry.getKey()
+ "; a template extension method must be static, non-private and must not return void");
}
for (MethodInfo method : found) {
produceExtensionMethod(index, extensionMethods, method, entry.getValue());
}
}
}
private void produceExtensionMethod(IndexView index, BuildProducer<TemplateExtensionMethodBuildItem> extensionMethods,
MethodInfo method, AnnotationInstance extensionAnnotation) {
// Analyze matchName and priority so that it could be used during validation
byte matchers = 0;
String matchName = null;
AnnotationValue matchNameValue = extensionAnnotation.value(ExtensionMethodGenerator.MATCH_NAME);
if (matchNameValue != null) {
matchName = matchNameValue.asString();
matchers++;
}View on GitHub (pinned to e1c734241f)
Solutions
- Make the extension method static and at least package-private (prefer public), with a non-void return type
- Add the first parameter as the extended type, e.g. public static String shout(String self)
- If the class should host no extensions, remove the @TemplateExtension annotation
- Use @TemplateExtension on individual methods if class-level discovery does not fit
Example fix
// before
@TemplateExtension
public class StringExt {
private void trimAll(String s) { } // private + void
}
// after
@TemplateExtension
public class StringExt {
public static String trimAll(String self) {
return self.strip();
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate an extension class before annotating it with @TemplateExtension
boolean valid = Modifier.isStatic(m.getModifiers())
&& !Modifier.isPrivate(m.getModifiers())
&& m.getReturnType() != void.class; Prevention
- Follow the canonical signature: public static ReturnType ext(BaseType self, ...)
- Never mark extension methods private or void-returning
- Only put @TemplateExtension on classes meant to host extensions
- Review the Qute extension method rules when upgrading Quarkus versions
When it happens
Trigger: Annotating a class with @TemplateExtension but its only candidate methods are instance (non-static) methods, private methods, or void-returning methods; the matchName/value/condition attributes on @TemplateExtension on individual methods disqualify all methods so `found` stays empty while no method-level annotation was seen (skippedMethodLevelAnnotation false).
Common situations: Copying an extension helper class into a CDI-aware project where methods became instance methods; accidentally marking the extension method private; writing a void mutating method expecting it to work as an extension.
Related errors
- Fragment [<fragmentId>] not defined in template <templateId>
- Template extension methods that share the namespace <namespa
- Type ${className} must be annotated with @Embeddable, becaus
- No suitable template variant found
- No template variant found
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/28bb4ceb8628d56f.
Report an issue: GitHub.