quarkusio/quarkus · error · RuntimeException

A background function cannot return a value

Error message

A background function cannot return a value

What it means

Google Cloud background functions (e.g. Pub/Sub, Firestore triggers) must return void. When a Funqy function bound to a background Cloud Function invocation produces a non-null output, FunqyCloudFunctionsBindingRecorder throws this RuntimeException after dispatching, because a background function has no response channel to deliver a value to.

Source

Thrown at extensions/funqy/funqy-google-cloud-functions/runtime/src/main/java/io/quarkus/funqy/gcp/functions/FunqyCloudFunctionsBindingRecorder.java:100

    /**
     * Handle RawBackgroundFunction
     *
     * @param event
     * @param context
     */
    public static void handle(String event, Context context) {
        //TODO allow to access the context from the function somehow.
        try {
            Object input = null;
            if (invoker.hasInput()) {
                input = reader.readValue(event);
            }
            FunqyServerResponse response = dispatch(input);

            Object value = response.getOutput().await().indefinitely();
            if (value != null) {
                throw new RuntimeException("A background function cannot return a value");
            }
        } catch (JacksonException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Handle CloudEventsFunction
     *
     * @param cloudEvent
     */
    public static void handle(CloudEvent cloudEvent) {
        FunqyServerResponse response = dispatch(cloudEvent);

        Object value = response.getOutput().await().indefinitely();
        if (value != null) {
            throw new RuntimeException("A background function cannot return a value");
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the background function's return type to void (or String/Uni that resolves to null) so no output is produced.
  2. If output is needed, bind the function to an HTTP-invoked Cloud Function instead of a background one.
  3. Wrap the value-producing logic in a function returning Uni<Void> or a CompletableFuture that completes with null.
  4. Exclude the function from background export via quarkus.funqy.export and register a separate void function.

Example fix

// before
public class MyFunctions {
    @Function
    public String process(Event in) { return "done"; }
}
// after
public class MyFunctions {
    @Function
    public void process(Event in) { /* side effects only */ }
}
Defensive patterns

Strategy: validation

Validate before calling

if (!java.lang.reflect.Modifier.class.getClass().equals(void.class)) { /* inspect method return type */ }
// At build/config time: assert the @Function method's return type is void before deploying as background
Method m = MyFunctions.class.getMethod("process", Event.class);
if (m.getReturnType() != void.class) throw new IllegalStateException("Background function must be void");

Type guard

boolean isBackgroundSafe(Method m) { return m.getReturnType() == void.class || Uni.class.equals(m.getReturnType()); }

Try / catch

try { dispatch(input); } catch (RuntimeException e) { if (e.getMessage().contains("background function cannot return")) { log.error("Fix function signature: return void", e); } throw e; }

Prevention

When it happens

Trigger: A Funqy function with a non-void return type is invoked via the background-function entry point handle(Object event): the function completes successfully, but response.getOutput().await().indefinitely() yields a non-null value.

Common situations: Developers define a Funqy @Function that returns a payload (e.g. a DTO) for request/response use, then deploy it as a GCP background/cloud-event function; or they reuse one function for both HTTP and background invocations.

Related errors


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