quarkusio/quarkus · error · io.quarkus.qute.TemplateException

Multiple checked templates exist for the template path %s:

Error message

Multiple checked templates exist for the template path %s:
	- %s
	- %s

What it means

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.

Source

Thrown at extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java:460

                if (method.isSynthetic() || method.isBridge() || method.parametersCount() != 0) {
                    continue;
                }
                reservedNames.add(method.name());
            }
            for (ClassInfo recordClass : index.getIndex().getAllKnownImplementations(recordInterfaceName)) {
                if (!recordClass.isRecord()) {
                    continue;
                }
                MethodInfo canonicalConstructor = recordClass.canonicalRecordConstructor();

                AnnotationInstance checkedTemplateAnnotation = recordClass.declaredAnnotation(Names.CHECKED_TEMPLATE);
                String fragmentId = getCheckedFragmentId(recordClass, checkedTemplateAnnotation);
                String templatePath = getCheckedTemplatePath(index.getIndex(), checkedTemplateAnnotation, fragmentId,
                        recordClass);
                String fullPath = templatePath + (fragmentId != null ? "$" + fragmentId : "");
                AnnotationTarget checkedTemplate = checkedTemplates.putIfAbsent(fullPath, recordClass);
                if (checkedTemplate != null) {
                    throw new TemplateException(
                            String.format(
                                    "Multiple checked templates exist for the template path %s:\n\t- %s\n\t- %s",
                                    fullPath, recordClass.name(), checkedTemplate));
                }

                if (!filePaths.contains(templatePath)
                        && isNotLocatedByCustomTemplateLocator(locatorPatternsBuildItem.getLocationPatterns(),
                                templatePath)) {
                    List<String> startsWith = new ArrayList<>();
                    for (String filePath : filePaths.getFilePaths()) {
                        if (filePath.startsWith(templatePath)
                                && filePath.charAt(templatePath.length()) == '.') {
                            startsWith.add(filePath);
                        }
                    }
                    if (startsWith.isEmpty()) {
                        throw new TemplateException(
                                "No template matching the path " + templatePath + " could be found for: "

View on GitHub (pinned to e1c734241f)

Solutions

  1. Find the two classes listed in the message and delete or rename one
  2. Give one of them an explicit distinct location: @CheckedTemplate(location="items/list2") or basePath=...
  3. If using records as template records, remove the leftover @CheckedTemplate interface for the same template
  4. Ensure fragment ids differ when two classes intentionally use the same template file with different fragments

Example fix

// before
// com.a.Templates: @CheckedTemplate(basePath="items") interface Templates { static native TemplateInstance list(); }
// com.b.Templates: @CheckedTemplate(basePath="items") interface Templates { static native TemplateInstance list(); }
// after
// com.a.Templates: basePath="items"
// com.b.Templates: @CheckedTemplate(basePath="orders") interface Templates { static native TemplateInstance list(); }
Defensive patterns

Strategy: validation

Validate before calling

// detect duplicate checked template base names before build
Set<String> seen = new HashSet<>();
for (Class<?> c : allCheckedTemplateClasses) {
    String path = c.getAnnotation(CheckedTemplate.class) != null
        ? c.getAnnotation(CheckedTemplate.class).basePath() + "/" + c.getSimpleName()
        : c.getName().replace('.', '/');
    if (!seen.add(path)) throw new IllegalStateException("Duplicate checked template path: " + path);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/889ce57f5759cad5. Report an issue: GitHub.