{"record":{"id":"070460bc3f24c2f8","repo":"quarkusio/quarkus","slug":"cannot-register-s-a-localized-message-bundle","errorCode":null,"errorMessage":"Cannot register [%s] - a localized message bundle interface exists for locale [%s]: %s","messagePattern":"Cannot register \\[(.+?)\\] - a localized message bundle interface exists for locale \\[(.+?)\\]: (.+?)","errorType":"exception","errorClass":"MessageBundleException","httpStatus":null,"severity":"error","filePath":"extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/MessageBundleProcessor.java","lineNumber":210,"sourceCode":"\n                    // Find localizations for each interface\n                    String defaultLocale = getDefaultLocale(bundleAnnotation, locales);\n                    List<ClassInfo> localized = new ArrayList<>();\n                    for (ClassInfo implementor : index.getKnownDirectSubinterfaces(bundleClass.name())) {\n                        localized.add(implementor);\n                    }\n                    Map<String, ClassInfo> localeToInterface = new HashMap<>();\n                    for (ClassInfo localizedInterface : localized) {\n                        String locale = localizedInterface.declaredAnnotation(Names.LOCALIZED).value().asString();\n                        if (defaultLocale.equals(locale)) {\n                            throw new MessageBundleException(\n                                    String.format(\n                                            \"Locale of [%s] conflicts with the locale [%s] of the default message bundle [%s]\",\n                                            localizedInterface, locale, bundleClass));\n                        }\n                        ClassInfo previous = localeToInterface.put(locale, localizedInterface);\n                        if (previous != null) {\n                            throw new MessageBundleException(String.format(\n                                    \"Cannot register [%s] - a localized message bundle interface exists for locale [%s]: %s\",\n                                    localizedInterface, locale, previous));\n                        }\n                        localizedInterfaces.add(localizedInterface.name());\n                    }\n\n                    // Find localized files\n                    Map<String, List<MessageFile>> localeToFiles = new HashMap<>();\n                    // Message templates not specified by a localized interface are looked up in a localized file (merge candidate)\n                    Map<String, List<MessageFile>> localeToMergeCandidates = new HashMap<>();\n                    for (MessageFile messageFile : messageFiles) {\n                        if (messageFile.matchesBundle(name)) {\n                            String locale = messageFile.getLocale(name);\n                            if (locale == null) {\n                                locale = defaultLocale;\n                            }\n                            ClassInfo localizedInterface = localeToInterface.get(locale);\n                            List<MessageFile> files;","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/MessageBundleProcessor.java#L192-L228","documentation":"MessageBundleException thrown at build time when two @Localized subinterfaces of the same @MessageBundle interface declare the same locale. Each locale can map to exactly one localized interface; a duplicate would make message lookup for that locale ambiguous. The build fails listing the new interface, the locale, and the previously registered interface that already holds it.","triggerScenarios":"Two subinterfaces extending the same bundle interface both annotated with the same @Localized value, e.g. @Localized(\"fr\") on AppMessages_fr in two packages, or @Localized(\"fr\") plus @Localized(\"fr-CA\") resolved/colliding as the same locale key in localeToInterface.","commonSituations":"Copy-pasting a localized interface and forgetting to change @Localized; splitting translations across modules where both define a bundle for the same language; regional variants like fr and fr_CA typos written identically in @Localized.","solutions":["Change one interface's @Localized value to a distinct locale or regional variant, e.g. @Localized(\"fr_CA\") vs @Localized(\"fr\").","Delete the duplicate localized interface if it adds nothing beyond the other one.","Move extra messages into .properties message files for the same locale instead of a second interface."],"exampleFix":"// before\n@Localized(\"fr\") public interface AppMessages_fr extends AppMessages { ... }\n@Localized(\"fr\") public interface AppMessages_fr2 extends AppMessages { ... }\n\n// after\n@Localized(\"fr\") public interface AppMessages_fr extends AppMessages { ... }\n@Localized(\"fr_CA\") public interface AppMessages_fr_ca extends AppMessages { ... }","handlingStrategy":"validation","validationCode":"// ensure each @Localized locale appears at most once per bundle:\nMap<String,String> seen = new HashMap<>();\nfor (Class<?> c : localizedInterfaces) {\n    String loc = c.getAnnotation(Localized.class).value();\n    if (seen.containsKey(loc)) throw new IllegalStateException(loc + \" already provided by \" + seen.get(loc));\n    seen.put(loc, c.getName());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use regional variants (fr vs fr_CA) instead of duplicating a base locale.","When copying a localized interface, immediately update the @Localized value and class name.","Prefer .properties message files for additional translations of the same locale rather than a second interface.","Keep all localized variants of a bundle in the same package so duplicates are easy to spot."],"tags":["quarkus","qute","i18n","locale","duplicate","message-bundle"],"backgroundTag":"locale-conflict","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"}