quarkusio/quarkus · error · TemplateException

A template extension method matching multiple names or a reg

Error message

A template extension method matching multiple names or a regular expression must declare at least two parameters and the second parameter must be string: 

What it means

When a template extension method matches multiple names (@TemplateExtension(matchNames=...) or matchRegex) or ANY, the generated code needs the second method parameter to receive the matched name at invocation time. Qute throws a TemplateException if the method has fewer than two parameters or the second parameter is not java.lang.String.

Source

Thrown at independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java:158

            if (priorityValue != null) {
                priority = priorityValue.asInt();
            }
        }
        if (priority == null) {
            priority = TemplateExtension.DEFAULT_PRIORITY;
        }

        if (matchRegex == null && extensionAnnotation != null) {
            AnnotationValue matchRegexValue = extensionAnnotation.value(MATCH_REGEX);
            if (matchRegexValue != null) {
                matchRegex = matchRegexValue.asString();
            }
        }

        if (matchRegex != null || !matchNames.isEmpty() || matchName.equals(TemplateExtension.ANY)) {
            // A string parameter is needed to match the name
            if (parameters.size() < 2 || !parameters.get(1).name().equals(DotNames.STRING)) {
                throw new TemplateException(
                        "A template extension method matching multiple names or a regular expression must declare at least two parameters and the second parameter must be string: "
                                + method);
            }
        }

        String baseName;
        if (declaringClass.enclosingClass() != null) {
            baseName = simpleName(declaringClass.enclosingClass()) + ValueResolverGenerator.NESTED_SEPARATOR
                    + simpleName(declaringClass);
        } else {
            baseName = simpleName(declaringClass);
        }
        String targetPackage = packageName(declaringClass.name());

        String suffix = SUFFIX + "_" + method.name() + "_" + sha1(parameters.toString());
        String generatedName = generatedNameFromTarget(targetPackage, baseName, suffix);
        String generatedClassName = generatedName.replace('/', '.');
        generatedTypes.add(generatedClassName);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add a second parameter of type java.lang.String to receive the matched name
  2. Remove matchRegex/matchNames/ANY and use a single fixed matchName if only one parameter is needed
  3. Use a matching suffix like '_suffix' naming convention instead of regex matching

Example fix

// before
@TemplateExtension(matchRegex = "cam[0-9]+")
static String convert(Object base) { ... }
// after
@TemplateExtension(matchRegex = "cam[0-9]+")
static String convert(Object base, String name) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// For matchRegex/matchNames/ANY extensions:
if ((ext.matchRegex().isPresent() || ext.matchNames().length > 0 || ext.matchName().equals(TemplateExtension.ANY))
    && (m.getParameterCount() < 2 || m.getParameterTypes()[1] != String.class))
    throw new IllegalStateException("Needs >=2 params, 2nd must be String: " + m);

Prevention

When it happens

Trigger: Declaring @TemplateExtension(matchRegex = "...") or matchNames/{ANY} on a method with only a base object parameter, or whose second parameter is not String. Raised by ExtensionMethodGenerator.generate at build time.

Common situations: Regex-matching extensions defined with only one parameter; forgetting that the matched name is passed as the 2nd parameter; using a non-String type (e.g. Object) for the name parameter.

Related errors


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