{"record":{"id":"4db4ba6efc2cba91","repo":"quarkusio/quarkus","slug":"message-bundle-interface-must-be-annotated-either","errorCode":null,"errorMessage":"Message bundle interface must be annotated either with @MessageBundle or with @Localized: ","messagePattern":"Message bundle interface must be annotated either with @MessageBundle or with @Localized: ","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/qute/runtime/src/main/java/io/quarkus/qute/i18n/MessageBundles.java","lineNumber":45,"sourceCode":"public final class MessageBundles {\n\n    public static final String ATTRIBUTE_LOCALE = TemplateInstance.LOCALE;\n    public static final String DEFAULT_LOCALE = \"<<default>>\";\n\n    private MessageBundles() {\n    }\n\n    public static <T> T get(Class<T> bundleInterface) {\n        return get(bundleInterface, null);\n    }\n\n    public static <T> T get(Class<T> bundleInterface, Localized localized) {\n        if (!bundleInterface.isInterface()) {\n            throw new IllegalArgumentException(\"Not a message bundle interface: \" + bundleInterface.getName());\n        }\n        if (!bundleInterface.isAnnotationPresent(MessageBundle.class)\n                && !bundleInterface.isAnnotationPresent(Localized.class)) {\n            throw new IllegalArgumentException(\n                    \"Message bundle interface must be annotated either with @MessageBundle or with @Localized: \"\n                            + bundleInterface.getName());\n        }\n        ArcContainer container = Arc.requireContainer();\n        InstanceHandle<T> handle = localized != null ? container.instance(bundleInterface, localized)\n                : container.instance(bundleInterface);\n        if (handle.isAvailable()) {\n            return handle.get();\n        }\n        throw new IllegalStateException(Qute.fmt(\n                \"Unable to obtain a message bundle for interface [{ifacename}]{#if loc} and locale [{loc.value}]{/if}\")\n                .data(\"ifacename\", bundleInterface.getName())\n                .data(\"loc\", localized)\n                .render());\n    }\n\n    /**\n     * Obtains a message bundle for the specified interface and the current locale.","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/qute/runtime/src/main/java/io/quarkus/qute/i18n/MessageBundles.java#L27-L63","documentation":"Message bundle interfaces must be annotated with @MessageBundle (base bundle) or @Localized (localized variants). MessageBundles.get() checks for either annotation before doing the CDI lookup and throws IllegalArgumentException when neither is present.","triggerScenarios":"Calling MessageBundles.get(iface) where iface is an interface but lacks both @MessageBundle and @Localized annotations — e.g. an unannotated plain interface passed by mistake.","commonSituations":"Defining a bundle interface and forgetting @MessageBundle; passing an unrelated interface to MessageBundles.get; generating interfaces without applying the annotation.","solutions":["Annotate the interface with @MessageBundle (e.g. @MessageBundle(locale=\"en\"))","For localized variants use @Localized instead","Verify the annotation is from io.quarkus.qute.i18n, not another similarly named annotation"],"exampleFix":"// before\npublic interface AppMessages { String hello(String name); }\n// after\n@MessageBundle(locale = \"en\")\npublic interface AppMessages { @Message(\"Hello {name}!\") String hello(String name); }","handlingStrategy":"validation","validationCode":"boolean annotated = MyMessages.class.isAnnotationPresent(MessageBundle.class)\n    || MyMessages.class.isAnnotationPresent(Localized.class);\nif (!annotated) throw new IllegalStateException(\"Add @MessageBundle or @Localized to \" + MyMessages.class);","typeGuard":"static <T> boolean hasBundleAnnotation(Class<T> iface) {\n    return iface.isAnnotationPresent(MessageBundle.class) || iface.isAnnotationPresent(Localized.class);\n}","tryCatchPattern":"try {\n    MyMessages m = MessageBundles.get(MyMessages.class);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"must be annotated either with @MessageBundle\")) {\n        throw new IllegalStateException(\"Annotate the interface with @MessageBundle\", e);\n    }\n    throw e;\n}","preventionTips":["Always start bundle interfaces with @MessageBundle from io.quarkus.qute.i18n","Add an ArchUnit or build check that all *Messages interfaces carry @MessageBundle","Check import statements when the IDE auto-imports a similarly named annotation"],"tags":["qute","i18n","messages","annotations"],"backgroundTag":"missing-required-annotation","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"}