quarkusio/quarkus · error · MessageBundleException

Default bundle method not found on %s: %s

Error message

Default bundle method not found on %s: %s

What it means

For the default bundle interface (the one declaring @MessageBundle), each method must be mirrored on every localized variant interface so translations line up. When a localized interface method cannot be matched to a method with the same name and parameter types on the default bundle interface, the build fails naming both the bundle interface and the offending method.

Source

Thrown at extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/MessageBundleProcessor.java:1049

                cc.method(methodDescOf(method), mc -> {
                    List<ParamVar> params = new ArrayList<>(method.parametersCount());
                    for (int i = 0; i < method.parametersCount(); i++) {
                        String paramName = method.parameterName(i);
                        params.add(mc.parameter(paramName != null ? paramName : "arg" + i, i));
                    }
                    if (!method.returnType().name().equals(DotNames.STRING)) {
                        throw new MessageBundleException(
                                String.format("A message bundle method must return java.lang.String: %s#%s",
                                        bundleInterface, method.name()));
                    }
                    LOG.debugf("Found message bundle method %s on %s", method, bundleInterface);

                    AnnotationInstance messageAnnotation;
                    if (defaultBundleInterface != null) {
                        MethodInfo defaultBundleMethod = bundleInterfaceWrapper.method(method.name(),
                                method.parameterTypes().toArray(new Type[] {}));
                        if (defaultBundleMethod == null) {
                            throw new MessageBundleException(
                                    String.format("Default bundle method not found on %s: %s", bundleInterface, method));
                        }
                        messageAnnotation = defaultBundleMethod.annotation(Names.MESSAGE);
                    } else {
                        messageAnnotation = method.annotation(Names.MESSAGE);
                    }

                    if (messageAnnotation == null) {
                        LOG.debugf("@Message not declared on %s#%s - using the default key/value", bundleInterface, method);
                        messageAnnotation = AnnotationInstance.builder(Names.MESSAGE).value(Message.DEFAULT_VALUE)
                                .add("name", Message.DEFAULT_NAME).build();
                    }

                    String key = getKey(method, messageAnnotation, defaultKeyValue);
                    if (key.equals(MESSAGE)) {
                        throw new MessageBundleException(String.format(
                                "A message bundle interface method must not use the key 'message' which is reserved for dynamic lookup; defined for %s#%s()",
                                bundleInterface, method.name()));

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the localized interface's method signature exactly match the default bundle method (same name, same parameter types).
  2. Remove methods from the localized interface that are not in the default bundle interface.
  3. Regenerate localized interfaces from the default bundle and re-apply translations.

Example fix

// before
// default: String hello(String name);
@Localized @Locale("de") interface AppMessagesDe extends AppMessages {
    String hello(String name, String greeting);
}

// after
@Localized @Locale("de") interface AppMessagesDe extends AppMessages {
    @Override
    String hello(String name);
}
Defensive patterns

Strategy: validation

Validate before calling

// Localized methods must match default bundle signatures
for (java.lang.reflect.Method m : AppMessagesDe.class.getDeclaredMethods()) {
    try {
        AppMessages.class.getMethod(m.getName(), m.getParameterTypes());
    } catch (NoSuchMethodException e) {
        throw new IllegalStateException("No matching default method: " + m, e);
    }
}

Prevention

When it happens

Trigger: A @Localized interface declares a method with a different signature (extra/missing parameter, different types) or an extra method that does not exist on the @MessageBundle interface it extends.

Common situations: Adding a parameter to the base bundle method but only partially updating localized interfaces; hand-writing localized interfaces with divergent signatures; merging translations that added methods present only in one locale interface.

Related errors


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