quarkusio/quarkus · error · MessageBundleException
Locale of [%s] conflicts with the locale [%s] of the default
Error message
Locale of [%s] conflicts with the locale [%s] of the default message bundle [%s]
What it means
MessageBundleException thrown at build time when a subinterface annotated @Localized("xx") uses the same locale as the default bundle's locale (from @MessageBundle(defaultLocale=...) or the application's quarkus.default-locale). The default bundle interface itself already serves that locale, so a separate @Localized interface for it is redundant and ambiguous. The build fails, naming the conflicting interface and locale.
Source
Thrown at extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/MessageBundleProcessor.java:203
if (found.containsKey(name)) {
throw new MessageBundleException(
String.format("Message bundle interface name conflict - [%s] is used for both [%s] and [%s]",
name, bundleClass, found.get(name)));
}
found.put(name, bundleClass);
// Find localizations for each interface
String defaultLocale = getDefaultLocale(bundleAnnotation, locales);
List<ClassInfo> localized = new ArrayList<>();
for (ClassInfo implementor : index.getKnownDirectSubinterfaces(bundleClass.name())) {
localized.add(implementor);
}
Map<String, ClassInfo> localeToInterface = new HashMap<>();
for (ClassInfo localizedInterface : localized) {
String locale = localizedInterface.declaredAnnotation(Names.LOCALIZED).value().asString();
if (defaultLocale.equals(locale)) {
throw new MessageBundleException(
String.format(
"Locale of [%s] conflicts with the locale [%s] of the default message bundle [%s]",
localizedInterface, locale, bundleClass));
}
ClassInfo previous = localeToInterface.put(locale, localizedInterface);
if (previous != null) {
throw new MessageBundleException(String.format(
"Cannot register [%s] - a localized message bundle interface exists for locale [%s]: %s",
localizedInterface, locale, previous));
}
localizedInterfaces.add(localizedInterface.name());
}
// Find localized files
Map<String, List<MessageFile>> localeToFiles = new HashMap<>();
// Message templates not specified by a localized interface are looked up in a localized file (merge candidate)
Map<String, List<MessageFile>> localeToMergeCandidates = new HashMap<>();
for (MessageFile messageFile : messageFiles) {View on GitHub (pinned to e1c734241f)
Solutions
- Remove the @Localized subinterface whose locale equals the default bundle locale — the base bundle already covers it.
- Change the @Localized value to a different locale, e.g. @Localized("de").
- Or change the bundle's default locale (@MessageBundle(locale="...")) so it no longer equals the localized interface's locale.
Example fix
// before (defaultLocale = "en")
@MessageBundle public interface AppMessages { @Message String hello(); }
@Localized("en") public interface AppMessages_en extends AppMessages { @Message String hello(); }
// after
@MessageBundle public interface AppMessages { @Message String hello(); }
@Localized("de") public interface AppMessages_de extends AppMessages { @Message String hello(); } Defensive patterns
Strategy: validation
Validate before calling
// ensure @Localized locales never equal the bundle default locale:
String defaultLocale = "en"; // @MessageBundle(locale=...) or quarkus.default-locale
for (Class<?> c : localizedInterfaces) {
String loc = c.getAnnotation(Localized.class).value();
if (loc.equals(defaultLocale)) throw new IllegalStateException(c + " duplicates default locale " + defaultLocale);
} Prevention
- Never create @Localized subinterfaces for the bundle's default locale — extend/override in the base interface instead.
- When changing quarkus.default-locale or @MessageBundle(locale=...), audit all @Localized values for collisions.
- Follow the naming convention XxxMessages_<locale> so mismatches are visible in code review.
- Centralize supported locales in a constant/list and reference it in reviews.
When it happens
Trigger: Default bundle locale is e.g. 'en' and someone creates interface AppMessages_en annotated @Localized("en"); or @MessageBundle(locale="en") while quarkus.default-locale is also en and a @Localized("en") subinterface exists.
Common situations: Adding localizations and mechanically including the base language; setting quarkus.default-locale to a new value (e.g. changing app default from en to de) which makes an existing @Localized("en") bundle suddenly collide (or the reverse); copying an existing localized interface and forgetting to change the @Localized value.
Related errors
- Cannot register [%s] - a localized message bundle interface
- Message bundle name [%s] declared on %s must be a valid name
- Message bundle interface name conflict - [%s] is used for bo
- @MessageBundle must be declared on an interface: {bundleClas
- A localized message bundle interface must extend a message b
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/2d19e206bfbb2286.
Report an issue: GitHub.