{"record":{"id":"eff9f6e9334029aa","repo":"quarkusio/quarkus","slug":"template-extension-method-declared-on-must-be-sta","errorCode":null,"errorMessage":"Template extension method declared on  must be static: ","messagePattern":"Template extension method declared on  must be static: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java","lineNumber":81,"sourceCode":"    public static final DotName TEMPLATE_EXTENSION = DotName.createSimple(TemplateExtension.class.getName());\n    public static final DotName TEMPLATE_ATTRIBUTE = DotName.createSimple(TemplateExtension.TemplateAttribute.class.getName());\n    public static final String SUFFIX = \"_Extension\" + ValueResolverGenerator.SUFFIX;\n    public static final String NAMESPACE_SUFFIX = \"_Namespace\" + SUFFIX;\n\n    public static final String MATCH_NAME = \"matchName\";\n    public static final String MATCH_NAMES = \"matchNames\";\n    public static final String MATCH_REGEX = \"matchRegex\";\n    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","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ExtensionMethodGenerator.java#L63-L99","documentation":"Qute template extension methods (value resolvers exposed via @TemplateExtension or namespace extension methods) must be static. ExtensionMethodGenerator.validate() throws IllegalStateException during build-time bytecode generation when the annotated method is an instance method, since Qute calls the method statically without a receiver instance.","triggerScenarios":"Declaring a template extension method as non-static — e.g. @TemplateExtension on an instance method of a CDI bean or helper class — then running Quarkus augmentation; building templates with a namespace method that isn't static.","commonSituations":"Migrating an older extension style to @TemplateExtension and forgetting 'static'; adding @TemplateExtension to a regular bean method; copying an example but dropping the static modifier.","solutions":["Add the static modifier to the extension method.","If the method needs instance state, make it static and pass required values as parameters, or use a different resolver approach (e.g. a ValueResolver/template data).","Ensure the class containing the method is indexed (not needed for static fix, but the class must be part of the app).","Rebuild with ./mvnw install after the change; the error occurs during augmentation."],"exampleFix":"// before\n@TemplateExtension\nString shout(String s) { return s.toUpperCase() + \"!\"; }\n// after\n@TemplateExtension\nstatic String shout(String s) { return s.toUpperCase() + \"!\"; }","handlingStrategy":"validation","validationCode":"// check before build\nfor (MethodInfo m : extensionMethods) {\n    if (!Modifier.isStatic(m.flags())) {\n        throw new IllegalStateException(\"@TemplateExtension method must be static: \" + m);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    quarkusBuild augmentation...\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"must be static\")) {\n        // add 'static' to the annotated extension method\n    }\n}","preventionTips":["Always declare @TemplateExtension methods static","Do not attach @TemplateExtension to CDI bean instance methods","If state is needed, pass values as parameters or use @TemplateData/ValueResolver instead"],"tags":["qute","template-extension","build-time","illegal-state","quarkus"],"backgroundTag":"extension-method-not-static","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}