quarkusio/quarkus · error · java.lang.IllegalStateException
Template extension methods that share the namespace <namespa
Error message
Template extension methods that share the namespace <namespace> must be declared on the same class; but declared on <class1> and <class2>
What it means
Thrown when two or more template extension methods declare the same @TemplateExtension namespace but are declared on different classes. Qute requires all extension methods of a given namespace to live on a single class so namespace resolution is unambiguous.
Source
Thrown at extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java:2100
Map<DotName, Map<String, List<TemplateExtensionMethodBuildItem>>> classToNamespaceExtensions = new HashMap<>();
Map<String, DotName> namespaceToClass = new HashMap<>();
for (TemplateExtensionMethodBuildItem templateExtension : templateExtensionMethods) {
String generatedValueResolverClass = existingValueResolvers.getGeneratedClass(templateExtension.getMethod());
if (generatedValueResolverClass != null) {
// A ValueResolver of a non-application class was already generated
generatedValueResolvers.add(generatedValueResolverClass);
continue;
}
if (templateExtension.hasNamespace()) {
// Group extension methods declared on the same class by namespace
DotName declaringClassName = templateExtension.getMethod().declaringClass().name();
DotName namespaceClassName = namespaceToClass.get(templateExtension.getNamespace());
if (namespaceClassName == null) {
namespaceToClass.put(templateExtension.getNamespace(), namespaceClassName);
} else if (!namespaceClassName.equals(declaringClassName)) {
throw new IllegalStateException("Template extension methods that share the namespace "
+ templateExtension.getNamespace() + " must be declared on the same class; but declared on "
+ namespaceClassName + " and " + declaringClassName);
}
Map<String, List<TemplateExtensionMethodBuildItem>> namespaceToExtensions = classToNamespaceExtensions
.get(declaringClassName);
if (namespaceToExtensions == null) {
namespaceToExtensions = new HashMap<>();
classToNamespaceExtensions.put(declaringClassName, namespaceToExtensions);
}
List<TemplateExtensionMethodBuildItem> namespaceMethods = namespaceToExtensions
.get(templateExtension.getNamespace());
if (namespaceMethods == null) {
namespaceMethods = new ArrayList<>();
namespaceToExtensions.put(templateExtension.getNamespace(), namespaceMethods);
}
namespaceMethods.add(templateExtension);
} else {
// Generate ValueResolver per extension methodView on GitHub (pinned to e1c734241f)
Solutions
- Move all methods using the same namespace into one class
- Change the namespace on one of the colliding classes to a distinct namespace
- Remove one of the duplicate extension methods if it is redundant
- If it comes from a third-party dependency, exclude/override that dependency or pick a new namespace in your code
Example fix
// before
class A { @TemplateExtension(namespace="money") static String fmt(BigDecimal v){...} }
class B { @TemplateExtension(namespace="money") static String shortFmt(BigDecimal v){...} }
// after
class A { @TemplateExtension(namespace="money")
static String fmt(BigDecimal v){...}
static String shortFmt(BigDecimal v){...} } Defensive patterns
Strategy: validation
Validate before calling
// Ensure each custom namespace is declared on exactly one class
Map<String, Long> nsCount = allExtensionClasses.stream()
.flatMap(c -> c.namespaces().stream())
.collect(Collectors.groupingBy(n -> n, Collectors.counting()));
List<String> dupes = nsCount.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).toList(); Prevention
- Keep all methods of a namespace in a single dedicated class
- Prefix namespaces with your app name to avoid dependency collisions
- Grep for @TemplateExtension(namespace = ...) when introducing a new namespace
- Document namespace ownership in team conventions
When it happens
Trigger: Two helper classes both annotated methods with @TemplateExtension(namespace = "cfg") or matching value; a namespace collision introduced after moving one extension method to a shared library class while a local copy remains.
Common situations: Splitting extension methods across utility classes during refactoring; two dependencies each defining extensions in the same custom namespace; copy-pasting an extension class and forgetting to change the namespace.
Related errors
- No template extension methods declared on <class>; a templat
- The namespace [%s] is defined by multiple @TemplateData and/
- No suitable template variant found
- No template variant found
- Message bundle name [%s] declared on %s must be a valid name
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/9592c5bb650a60be.
Report an issue: GitHub.