{"record":{"id":"45fa43a4936e0877","repo":"quarkusio/quarkus","slug":"template-extension-method-declared-on-must-not-be","errorCode":null,"errorMessage":"Template extension method declared on  must not be private: ","messagePattern":"Template extension method declared on  must not be private: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java","lineNumber":89,"sourceCode":"    public static final String PRIORITY = \"priority\";\n    public static final String NAMESPACE = \"namespace\";\n    public static final String PATTERN = \"pattern\";\n\n    public ExtensionMethodGenerator(IndexView index, ClassOutput classOutput) {\n        super(index, classOutput);\n    }\n\n    public static void validate(MethodInfo method, String namespace) {\n        if (!Modifier.isStatic(method.flags())) {\n            throw new IllegalStateException(\n                    \"Template extension method declared on \" + method.declaringClass().name() + \"  must be static: \" + method);\n        }\n        if (method.returnType().kind() == Kind.VOID) {\n            throw new IllegalStateException(\"Template extension method declared on \" + method.declaringClass().name()\n                    + \" must not return void: \" + method);\n        }\n        if (Modifier.isPrivate(method.flags())) {\n            throw new IllegalStateException(\"Template extension method declared on \" + method.declaringClass().name()\n                    + \" must not be private: \" + method);\n        }\n    }\n\n    /**\n     *\n     * @param method\n     * @param matchName\n     * @param matchNames\n     * @param matchRegex\n     * @param priority\n     * @return the fully qualified name of the generated class\n     */\n    public String generate(MethodInfo method, String matchName, List<String> matchNames, String matchRegex, Integer priority) {\n\n        LOG.debugf(\"Generating resolver for extension method declared on %s: %s\", method.declaringClass(), method);\n\n        AnnotationInstance extensionAnnotation = method.annotation(TEMPLATE_EXTENSION);","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java#L71-L107","documentation":"Template extension methods are invoked statically from generated code without an instance of the declaring class. Qute rejects any @TemplateExtension method that is private because it cannot be invoked from the generated resolver class.","triggerScenarios":"Annotating a private static method with @TemplateExtension, or making a previously package-private/public extension method private; detected by ExtensionMethodGenerator.validate during build.","commonSituations":"Narrowing visibility during refactoring; helper methods annotated by mistake; extension methods defined inside another class as private helpers.","solutions":["Make the method at least package-private or public (keep it static)","Remove the @TemplateExtension annotation if the method should not be exposed to templates","Move the method to a dedicated extension class with appropriate visibility"],"exampleFix":"// before\n@TemplateExtension\nprivate static String slugify(String val) { ... }\n// after\n@TemplateExtension\nstatic String slugify(String val) { ... }","handlingStrategy":"validation","validationCode":"if (java.lang.reflect.Modifier.isPrivate(m.getModifiers()))\n    throw new IllegalStateException(\"@TemplateExtension method must not be private: \" + m);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep extension methods package-private or public","Avoid narrowing visibility of annotated methods during refactoring","Grep for @TemplateExtension on private methods in CI"],"tags":["qute","template-extension","build-time","visibility"],"backgroundTag":"private-template-extension-method","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"}