quarkusio/quarkus · error · io.quarkus.qute.TemplateException
Incompatible checked template return type: <returnType> only
Error message
Incompatible checked template return type: <returnType> only <supportedAdaptors>
What it means
Same family as error 1576 but hit when the return type is a class type not equal to TemplateInstance and no CheckedTemplateAdapter is registered for that exact type name. The build fails listing only the supported adaptor types.
Source
Thrown at extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java:374
NativeCheckedTemplateEnhancer enhancer = new NativeCheckedTemplateEnhancer();
for (MethodInfo method : targetClass.methods()) {
// only keep native static methods
if (!Modifier.isStatic(method.flags())
|| !Modifier.isNative(method.flags())) {
continue;
}
// check its return type
if (method.returnType().kind() != Type.Kind.CLASS) {
throw new TemplateException("Incompatible checked template return type: " + method.returnType()
+ " only " + supportedAdaptors);
}
DotName returnTypeName = method.returnType().asClassType().name();
CheckedTemplateAdapter adaptor = null;
// if it's not the default template instance, try to find an adapter
if (!returnTypeName.equals(Names.TEMPLATE_INSTANCE)) {
adaptor = adaptors.get(returnTypeName);
if (adaptor == null)
throw new TemplateException("Incompatible checked template return type: " + method.returnType()
+ " only " + supportedAdaptors);
}
String fragmentId = getCheckedFragmentId(method, annotation);
String templatePath = getCheckedTemplatePath(index.getIndex(), annotation, fragmentId, targetClass, method);
String fullPath = templatePath + (fragmentId != null ? "$" + fragmentId : "");
AnnotationTarget checkedTemplate = checkedTemplates.putIfAbsent(fullPath, method);
if (checkedTemplate != null) {
throw new TemplateException(
String.format(
"Multiple checked templates exist for the template path %s:\n\t- %s: %s\n\t- %s",
fullPath, method.declaringClass().name(), method,
checkedTemplate));
}
if (!filePaths.contains(templatePath)
&& isNotLocatedByCustomTemplateLocator(locatorPatternsBuildItem.getLocationPatterns(),
templatePath)) {
List<String> startsWith = new ArrayList<>();
for (String filePath : filePaths.getFilePaths()) {View on GitHub (pinned to e1c734241f)
Solutions
- Return TemplateInstance from the @CheckedTemplate method
- If returning a custom wrapper, implement and register a CheckedTemplateAdapter
- Check that the intended return type matches one listed in the error's supportedAdaptors
Example fix
// before @CheckedTemplate static native String hello(); // after @CheckedTemplate static native TemplateInstance hello();
Defensive patterns
Strategy: type-guard
Validate before calling
// ArchUnit/test rule: no primitive/String/Uni returns on @CheckedTemplate if (!TemplateInstance.class.equals(m.getReturnType())) throw new AssertionError(...);
Type guard
static boolean returnsTemplateInstance(Method m) {
return m.getReturnType() == TemplateInstance.class;
} Prevention
- Never return raw domain types or reactive wrappers from checked templates
- Code-review checklist item for new @CheckedTemplate methods
When it happens
Trigger: A @CheckedTemplate static native method returns e.g. Uni<TemplateInstance>, String, or a custom DTO, and no CheckedTemplateAdapter is registered for that returned type name.
Common situations: Mistakenly declaring the raw entity type instead of TemplateInstance; copying patterns from REST where Uni<Response> works; missing qute adaptation extension for a reactive type.
Related errors
- Incompatible checked template return type: {returnType} only
- Multiple checked templates exist for the template path %s:
- No template matching the path <templatePath> could be found
- Unable to render config roots for top level prefix: ${topLev
- Unable to render config roots for specific file: ${fileName}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/be0de119f1dfc861.
Report an issue: GitHub.