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

  1. Remove the @Localized subinterface whose locale equals the default bundle locale — the base bundle already covers it.
  2. Change the @Localized value to a different locale, e.g. @Localized("de").
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/2d19e206bfbb2286. Report an issue: GitHub.