quarkusio/quarkus · error · MessageBundleException

A message bundle method must return java.lang.String: %s#%s

Error message

A message bundle method must return java.lang.String: %s#%s

What it means

Message bundle interface methods are generated to return localized text, so every method must declare java.lang.String as its return type. If a method returns anything else (int, StringBuilder, custom type, void), MessageBundleProcessor throws during build for that method.

Source

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

                cc.extends_(ClassDesc.of(defaultBundleImpl));
            }
            cc.defaultConstructor();

            // key -> method
            Map<String, MessageMethod> keyMap = new LinkedHashMap<>();
            List<MethodInfo> methods = new ArrayList<>(bundleInterfaceWrapper.methods());
            // Sort methods
            methods.sort(Comparator.comparing(MethodInfo::name).thenComparing(Comparator.comparing(MethodInfo::toString)));

            for (MethodInfo method : methods) {
                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);
                    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the method's return type to String: `String hello(String name);`
  2. If structured data is needed, return String of the rendered message and parse in the caller, or move non-message logic out of the bundle interface.
  3. Rebuild to confirm all bundle methods now return String.

Example fix

// before
@Message("Hello {name}")
StringBuilder hello(String name);

// after
@Message("Hello {name}")
String hello(String name);
Defensive patterns

Strategy: validation

Validate before calling

// Every bundle method must return String
for (java.lang.reflect.Method m : AppMessages.class.getMethods()) {
    if (m.getDeclaringClass() != AppMessages.class) continue;
    if (m.getReturnType() != String.class) {
        throw new IllegalStateException("Must return String: " + m);
    }
}

Prevention

When it happens

Trigger: Declaring `StringBuilder hello(String name);` or `int count();` on a @MessageBundle interface; accidental generic/wrapper return types like `Object` or `Optional<String>`.

Common situations: Copying method signatures from a service class into the bundle interface; auto-completing the wrong overload; refactoring the return type for one purpose and forgetting templates need plain Strings.

Related errors


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