{"record":{"id":"889ce57f5759cad5","repo":"quarkusio/quarkus","slug":"multiple-checked-templates-exist-for-the-template-889ce5","errorCode":null,"errorMessage":"Multiple checked templates exist for the template path %s:\n\t- %s\n\t- %s","messagePattern":"Multiple checked templates exist for the template path (.+?):\n\t- (.+?)\n\t- (.+?)","errorType":"exception","errorClass":"io.quarkus.qute.TemplateException","httpStatus":null,"severity":"error","filePath":"extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java","lineNumber":460,"sourceCode":"                if (method.isSynthetic() || method.isBridge() || method.parametersCount() != 0) {\n                    continue;\n                }\n                reservedNames.add(method.name());\n            }\n            for (ClassInfo recordClass : index.getIndex().getAllKnownImplementations(recordInterfaceName)) {\n                if (!recordClass.isRecord()) {\n                    continue;\n                }\n                MethodInfo canonicalConstructor = recordClass.canonicalRecordConstructor();\n\n                AnnotationInstance checkedTemplateAnnotation = recordClass.declaredAnnotation(Names.CHECKED_TEMPLATE);\n                String fragmentId = getCheckedFragmentId(recordClass, checkedTemplateAnnotation);\n                String templatePath = getCheckedTemplatePath(index.getIndex(), checkedTemplateAnnotation, fragmentId,\n                        recordClass);\n                String fullPath = templatePath + (fragmentId != null ? \"$\" + fragmentId : \"\");\n                AnnotationTarget checkedTemplate = checkedTemplates.putIfAbsent(fullPath, recordClass);\n                if (checkedTemplate != null) {\n                    throw new TemplateException(\n                            String.format(\n                                    \"Multiple checked templates exist for the template path %s:\\n\\t- %s\\n\\t- %s\",\n                                    fullPath, recordClass.name(), checkedTemplate));\n                }\n\n                if (!filePaths.contains(templatePath)\n                        && isNotLocatedByCustomTemplateLocator(locatorPatternsBuildItem.getLocationPatterns(),\n                                templatePath)) {\n                    List<String> startsWith = new ArrayList<>();\n                    for (String filePath : filePaths.getFilePaths()) {\n                        if (filePath.startsWith(templatePath)\n                                && filePath.charAt(templatePath.length()) == '.') {\n                            startsWith.add(filePath);\n                        }\n                    }\n                    if (startsWith.isEmpty()) {\n                        throw new TemplateException(\n                                \"No template matching the path \" + templatePath + \" could be found for: \"","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java#L442-L478","documentation":"Each checked template path must map to exactly one @CheckedTemplate class/interface (or template record). collectCheckedTemplates keys checked templates by full path (path + optional '$' + fragmentId); if two distinct classes resolve to the same fullPath the build fails with this TemplateException listing both classes.","triggerScenarios":"Two @CheckedTemplate interfaces in different packages whose base names produce the same template path (e.g. both default to 'ItemResource/item'); a template record class and an interface both declared for the same template path; duplicate fragment-ids for the same template.","commonSituations":"Copying an existing checked-template interface into a new package without adjusting @CheckedTemplate(basePath=...); refactoring a class into a record-based template record while leaving the old interface; accidental duplicate nested interfaces with identical names.","solutions":["Find the two classes listed in the message and delete or rename one","Give one of them an explicit distinct location: @CheckedTemplate(location=\"items/list2\") or basePath=...","If using records as template records, remove the leftover @CheckedTemplate interface for the same template","Ensure fragment ids differ when two classes intentionally use the same template file with different fragments"],"exampleFix":"// before\n// com.a.Templates: @CheckedTemplate(basePath=\"items\") interface Templates { static native TemplateInstance list(); }\n// com.b.Templates: @CheckedTemplate(basePath=\"items\") interface Templates { static native TemplateInstance list(); }\n// after\n// com.a.Templates: basePath=\"items\"\n// com.b.Templates: @CheckedTemplate(basePath=\"orders\") interface Templates { static native TemplateInstance list(); }","handlingStrategy":"validation","validationCode":"// detect duplicate checked template base names before build\nSet<String> seen = new HashSet<>();\nfor (Class<?> c : allCheckedTemplateClasses) {\n    String path = c.getAnnotation(CheckedTemplate.class) != null\n        ? c.getAnnotation(CheckedTemplate.class).basePath() + \"/\" + c.getSimpleName()\n        : c.getName().replace('.', '/');\n    if (!seen.add(path)) throw new IllegalStateException(\"Duplicate checked template path: \" + path);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give each @CheckedTemplate interface a unique basePath or explicit location","Avoid copying checked-template interfaces between packages unchanged","Delete obsolete interfaces when converting to template records","Review the two classes named in the error and keep exactly one per path"],"tags":["qute","build-time","duplicate","checked-template"],"backgroundTag":"duplicate-checked-template-path","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}