quarkusio/quarkus · error · NullPointerException

Mapper returned null

Error message

Mapper returned null

What it means

When streaming a Multi of items, RestMulti uses the `dataExtractor` function to map each item to the Multi/actual data to emit. If the mapper returns null the framework cannot represent the item and signals a NullPointerException with the 'Mapper returned null' message, per reactive-streams rules that onNext values must be non-null.

Source

Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/RestMulti.java:318

             */
            @Override
            public void onSubscribe(Flow.Subscription subscription) {
                if (secondUpstream.compareAndSet(null, subscription)) {
                    long r = requested.getAndSet(0L);
                    if (r != 0L) {
                        subscription.request(r);
                    }
                }
            }

            @Override
            public void onItem(I item) {
                Multi<? extends O> publisher;

                try {
                    publisher = dataExtractor.apply(item);
                    if (publisher == null) {
                        throw new NullPointerException(MAPPER_RETURNED_NULL);
                    }
                    if (headersExtractor != null) {
                        headers.set(headersExtractor.apply(item));
                    }
                    if (statusExtractor != null) {
                        status.set(statusExtractor.apply(item));
                    }
                } catch (Throwable ex) {
                    downstream.onError(ex);
                    return;
                }

                publisher.subscribe(this);
            }

            @Override
            public void onFailure(Throwable failure) {
                downstream.onError(failure);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Return a non-null value from the mapper — e.g. return an empty collection/instance or use `Optional.orElse(...)` before extracting.
  2. Filter out items that would map to null before the RestMulti stage: `multi.filter(i -> extract(i) != null)`.
  3. Fix the mapper logic so nulls (missing keys, empty optionals) are handled explicitly instead of propagated.

Example fix

// before
RestMulti.fromMulti(multi, item -> item.getPayload(), null, null).build(); // getPayload() may be null
// after
RestMulti.fromMulti(multi,
    item -> java.util.Objects.requireNonNullElse(item.getPayload(), Payload.empty()),
    null, null).build();
Defensive patterns

Strategy: validation

Validate before calling

multi = multi.filter(item -> extractData(item) != null);

Type guard

boolean isExtractable(Item item) {
    return item != null && item.getPayload() != null;
}

Try / catch

try {
    return RestMulti.fromMulti(multi, dataExtractor, null, null).build();
} catch (NullPointerException e) {
    LOG.error("Data extractor returned null", e);
    throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}

Prevention

When it happens

Trigger: Using `RestMulti.fromMulti(multi, dataExtractor, ...)` where `dataExtractor.apply(item)` returns null for any emitted item — e.g. a mapper that unwraps an Optional, looks up a field that is absent, or returns null for a sentinel element.

Common situations: Mapping DTOs where an optional field is missing; `map.get(key)` returning null for a missing key; extracting from records/entities where a nullable column is null; mapper logic returning null as a 'skip' signal instead of filtering.

Related errors


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