quarkusio/quarkus · error · java.lang.IllegalArgumentException
Not a message bundle interface:
Error message
Not a message bundle interface:
What it means
MessageBundles.get() resolves a CDI bean implementing the given message bundle interface at runtime. Before lookup it validates the argument is an interface; passing a class throws IllegalArgumentException('Not a message bundle interface: ...').
Source
Thrown at extensions/qute/runtime/src/main/java/io/quarkus/qute/i18n/MessageBundles.java:41
import io.quarkus.qute.TemplateInstance;
import io.quarkus.qute.Variant;
import io.quarkus.qute.runtime.MessageBundleRecorder.BundleContext;
public final class MessageBundles {
public static final String ATTRIBUTE_LOCALE = TemplateInstance.LOCALE;
public static final String DEFAULT_LOCALE = "<<default>>";
private MessageBundles() {
}
public static <T> T get(Class<T> bundleInterface) {
return get(bundleInterface, null);
}
public static <T> T get(Class<T> bundleInterface, Localized localized) {
if (!bundleInterface.isInterface()) {
throw new IllegalArgumentException("Not a message bundle interface: " + bundleInterface.getName());
}
if (!bundleInterface.isAnnotationPresent(MessageBundle.class)
&& !bundleInterface.isAnnotationPresent(Localized.class)) {
throw new IllegalArgumentException(
"Message bundle interface must be annotated either with @MessageBundle or with @Localized: "
+ bundleInterface.getName());
}
ArcContainer container = Arc.requireContainer();
InstanceHandle<T> handle = localized != null ? container.instance(bundleInterface, localized)
: container.instance(bundleInterface);
if (handle.isAvailable()) {
return handle.get();
}
throw new IllegalStateException(Qute.fmt(
"Unable to obtain a message bundle for interface [{ifacename}]{#if loc} and locale [{loc.value}]{/if}")
.data("ifacename", bundleInterface.getName())
.data("loc", localized)
.render());View on GitHub (pinned to e1c734241f)
Solutions
- Pass only the message bundle interface (annotated with @MessageBundle or @Localized)
- If the type became a class, restore it as an interface to keep bundle support
- Check imports — make sure you reference the interface, not a similarly named impl class
Example fix
// before MyMessages m = MessageBundles.get(MyMessagesImpl.class); // after MyMessages m = MessageBundles.get(MyMessages.class);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!bundleInterface.isInterface()) {
throw new IllegalArgumentException(bundleInterface + " is not an interface");
} Type guard
static <T> boolean isBundleCandidate(Class<T> c) {
return c.isInterface() && (c.isAnnotationPresent(MessageBundle.class) || c.isAnnotationPresent(Localized.class));
} Try / catch
try {
MyMessages m = MessageBundles.get(MyMessages.class);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Not a message bundle interface")) {
throw new IllegalStateException("Pass the bundle interface, not a class", e);
}
throw e;
} Prevention
- Keep bundle types as interfaces, never refactor them to abstract classes
- Type the MessageBundles.get call against the annotated interface
- Rely on IDE generics: get() will not accept non-interface types without warnings if generics are used correctly
When it happens
Trigger: Calling MessageBundles.get(SomeClass.class) or MessageBundles.get(iface, locale) where the Class argument is a concrete class, enum, or record rather than an interface.
Common situations: Autocompleting to a wrong class type; confusing MessageBundles.get with a generic service locator API; refactoring an interface into an abstract class while call sites remain.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Message bundle interface must be annotated either with @Mess
- Unable to obtain a message bundle for interface [{ifacename}
- Bean not found for localized interface [{e.value}] and local
- Multiple beans found for localized interface [{e.value}] and
- Locale of [%s] conflicts with the locale [%s] of the default
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/14535973f0f616f5.
Report an issue: GitHub.