{"record":{"id":"1c1361574313c5a6","repo":"quarkusio/quarkus","slug":"incompatible-checked-template-return-type-return","errorCode":null,"errorMessage":"Incompatible checked template return type: {returnType} only {supportedAdaptors}","messagePattern":"Incompatible checked template return type: (.+?) only (.+?)","errorType":"exception","errorClass":"TemplateException","httpStatus":null,"severity":"error","filePath":"extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java","lineNumber":365,"sourceCode":"        for (AnnotationInstance annotation : index.getIndex().getAnnotations(Names.CHECKED_TEMPLATE)) {\n            if (annotation.target().kind() != Kind.CLASS) {\n                continue;\n            }\n            ClassInfo targetClass = annotation.target().asClass();\n            if (targetClass.isRecord()) {\n                // Template records are processed separately\n                continue;\n            }\n            NativeCheckedTemplateEnhancer enhancer = new NativeCheckedTemplateEnhancer();\n            for (MethodInfo method : targetClass.methods()) {\n                // only keep native static methods\n                if (!Modifier.isStatic(method.flags())\n                        || !Modifier.isNative(method.flags())) {\n                    continue;\n                }\n                // check its return type\n                if (method.returnType().kind() != Type.Kind.CLASS) {\n                    throw new TemplateException(\"Incompatible checked template return type: \" + method.returnType()\n                            + \" only \" + supportedAdaptors);\n                }\n                DotName returnTypeName = method.returnType().asClassType().name();\n                CheckedTemplateAdapter adaptor = null;\n                // if it's not the default template instance, try to find an adapter\n                if (!returnTypeName.equals(Names.TEMPLATE_INSTANCE)) {\n                    adaptor = adaptors.get(returnTypeName);\n                    if (adaptor == null)\n                        throw new TemplateException(\"Incompatible checked template return type: \" + method.returnType()\n                                + \" only \" + supportedAdaptors);\n                }\n                String fragmentId = getCheckedFragmentId(method, annotation);\n                String templatePath = getCheckedTemplatePath(index.getIndex(), annotation, fragmentId, targetClass, method);\n                String fullPath = templatePath + (fragmentId != null ? \"$\" + fragmentId : \"\");\n                AnnotationTarget checkedTemplate = checkedTemplates.putIfAbsent(fullPath, method);\n                if (checkedTemplate != null) {\n                    throw new TemplateException(\n                            String.format(","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java#L347-L383","documentation":"Methods annotated @CheckedTemplate must be static/native and return a supported adaptor type: TemplateInstance or a type with a registered CheckedTemplateAdapter. A non-TemplateInstance return type without a registered adapter causes this TemplateException.","triggerScenarios":"A @CheckedTemplate method declares a return type that is neither TemplateInstance nor a registered adapted type (e.g. a custom wrapper without registering an adapter).","commonSituations":"Upgrading Quarkus where adaptor registration requirements changed; custom template wrapper classes used with @CheckedTemplate; forgetting to register an adapter build item for a custom type.","solutions":["Change the method return type to TemplateInstance (or a supported type)","Register a CheckedTemplateAdapterBuildItem for the custom return type in a deployment module","Remove @CheckedTemplate if the method is not a checked template accessor"],"exampleFix":"// before\nclass Templates {\n    @CheckedTemplate\n    static native MyWrapper page(); // no adapter\n}\n// after\nclass Templates {\n    @CheckedTemplate\n    static native TemplateInstance page();\n}\n","handlingStrategy":"type-guard","validationCode":"// Ensure all @CheckedTemplate methods return TemplateInstance\nfor (Method m : Templates.class.getDeclaredMethods()) {\n    if (m.isAnnotationPresent(CheckedTemplate.class)\n        && !TemplateInstance.class.isAssignableFrom(m.getReturnType()))\n        throw new IllegalStateException(m + \" must return TemplateInstance\");\n}","typeGuard":"static boolean isValidCheckedTemplate(Method m) {\n    return TemplateInstance.class.equals(m.getReturnType());\n}","tryCatchPattern":null,"preventionTips":["Always declare @CheckedTemplate methods as `static native TemplateInstance`","Register CheckedTemplateAdapterBuildItem for any custom wrapper type","Keep wrapper/adaptor pairs tested together"],"tags":["qute","checked-templates","return-type"],"backgroundTag":"checked-template-return-type","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}