{"record":{"id":"60a400086dd02f34","repo":"quarkusio/quarkus","slug":"a-template-extension-method-matching-multiple-name","errorCode":null,"errorMessage":"A template extension method matching multiple names or a regular expression must declare at least two parameters and the second parameter must be string: ","messagePattern":"A template extension method matching multiple names or a regular expression must declare at least two parameters and the second parameter must be string: ","errorType":"exception","errorClass":"TemplateException","httpStatus":null,"severity":"error","filePath":"independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java","lineNumber":158,"sourceCode":"            if (priorityValue != null) {\n                priority = priorityValue.asInt();\n            }\n        }\n        if (priority == null) {\n            priority = TemplateExtension.DEFAULT_PRIORITY;\n        }\n\n        if (matchRegex == null && extensionAnnotation != null) {\n            AnnotationValue matchRegexValue = extensionAnnotation.value(MATCH_REGEX);\n            if (matchRegexValue != null) {\n                matchRegex = matchRegexValue.asString();\n            }\n        }\n\n        if (matchRegex != null || !matchNames.isEmpty() || matchName.equals(TemplateExtension.ANY)) {\n            // A string parameter is needed to match the name\n            if (parameters.size() < 2 || !parameters.get(1).name().equals(DotNames.STRING)) {\n                throw new TemplateException(\n                        \"A template extension method matching multiple names or a regular expression must declare at least two parameters and the second parameter must be string: \"\n                                + method);\n            }\n        }\n\n        String baseName;\n        if (declaringClass.enclosingClass() != null) {\n            baseName = simpleName(declaringClass.enclosingClass()) + ValueResolverGenerator.NESTED_SEPARATOR\n                    + simpleName(declaringClass);\n        } else {\n            baseName = simpleName(declaringClass);\n        }\n        String targetPackage = packageName(declaringClass.name());\n\n        String suffix = SUFFIX + \"_\" + method.name() + \"_\" + sha1(parameters.toString());\n        String generatedName = generatedNameFromTarget(targetPackage, baseName, suffix);\n        String generatedClassName = generatedName.replace('/', '.');\n        generatedTypes.add(generatedClassName);","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java#L140-L176","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add a second parameter of type java.lang.String to receive the matched name","Remove matchRegex/matchNames/ANY and use a single fixed matchName if only one parameter is needed","Use a matching suffix like '_suffix' naming convention instead of regex matching"],"exampleFix":"// before\n@TemplateExtension(matchRegex = \"cam[0-9]+\")\nstatic String convert(Object base) { ... }\n// after\n@TemplateExtension(matchRegex = \"cam[0-9]+\")\nstatic String convert(Object base, String name) { ... }","handlingStrategy":"validation","validationCode":"// For matchRegex/matchNames/ANY extensions:\nif ((ext.matchRegex().isPresent() || ext.matchNames().length > 0 || ext.matchName().equals(TemplateExtension.ANY))\n    && (m.getParameterCount() < 2 || m.getParameterTypes()[1] != String.class))\n    throw new IllegalStateException(\"Needs >=2 params, 2nd must be String: \" + m);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember the matched name is delivered as the 2nd String parameter","Check the @TemplateExtension javadoc for signature rules","Keep regex/multi-name extensions in one well-tested class"],"tags":["qute","template-extension","build-time","signature"],"backgroundTag":"template-extension-signature-mismatch","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"}