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
- Return a non-null value from the mapper — e.g. return an empty collection/instance or use `Optional.orElse(...)` before extracting.
- Filter out items that would map to null before the RestMulti stage: `multi.filter(i -> extract(i) != null)`.
- 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
- Make dataExtractor total: return an empty value instead of null for missing data.
- Use Objects.requireNonNullElse or Optional.orElse inside mappers.
- Filter nullable items upstream before the RestMulti stage.
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
- The subscriber must not be `null`
- Demand must be greater than zero
- service interface descriptor file path cannot be null
- Cannot attach headers to a null client
- Compression cannot be null
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f4eac972baef840a.
Report an issue: GitHub.