ReactiveX/RxJava · error · IllegalArgumentException
errors is empty
Error message
errors is empty
What it means
Thrown by the CompositeException constructor when, after flattening nested CompositeExceptions, replacing null elements with NullPointerException, and de-duplicating, the resulting exception list is empty. This is a programming error: a CompositeException must wrap at least one real cause. An empty input collection, or a collection containing only nulls/empty nested composites, triggers it.
Source
Thrown at src/main/java/io/reactivex/rxjava4/exceptions/CompositeException.java:78
*
* @throws IllegalArgumentException if <code>errors</code> is empty.
*/
public CompositeException(@NonNull Iterable<? extends Throwable> errors) {
Set<Throwable> deDupedExceptions = new LinkedHashSet<>();
if (errors != null) {
for (Throwable ex : errors) {
if (ex instanceof CompositeException ce) {
deDupedExceptions.addAll(ce.getExceptions());
} else {
deDupedExceptions.add(Objects.requireNonNullElseGet(ex,
() -> new NullPointerException("Throwable was null!")));
}
}
} else {
deDupedExceptions.add(new NullPointerException("errors was null"));
}
if (deDupedExceptions.isEmpty()) {
throw new IllegalArgumentException("errors is empty");
}
List<Throwable> localExceptions = new ArrayList<>(deDupedExceptions);
this.exceptions = Collections.unmodifiableList(localExceptions);
this.message = exceptions.size() + " exceptions occurred. ";
}
/**
* Retrieves the list of exceptions that make up the {@code CompositeException}.
*
* @return the exceptions that make up the {@code CompositeException}, as a {@link List} of {@link Throwable}s
*/
@NonNull
public List<Throwable> getExceptions() {
return exceptions;
}
@Override
@NonNullView on GitHub (pinned to a8ab535614)
Solutions
- Before constructing a CompositeException, check that the list is non-empty and contains at least one non-null Throwable.
- If the aggregation legitimately produced no errors, skip creating the CompositeException entirely (return success instead).
- Filter nulls out of the list and verify size > 0 before passing it in.
- Add a test: an empty list throws, a single-element list succeeds, a list of nulls becomes a single NullPointerException-wrapped cause (non-empty, so no throw).
Example fix
// before
List<Throwable> errs = collectErrors(tasks);
throw new CompositeException(errs); // throws 'errors is empty' if errs is empty
// after
List<Throwable> errs = collectErrors(tasks);
if (errs.isEmpty()) {
return Result.success();
}
throw new CompositeException(errs); Defensive patterns
Strategy: validation
Validate before calling
void throwIfAny(List<Throwable> errors) {
List<Throwable> real = errors.stream()
.filter(Objects::nonNull)
.toList();
if (real.isEmpty()) return; // nothing to wrap
throw new CompositeException(real);
} Try / catch
try {
throw new CompositeException(errors);
} catch (IllegalArgumentException e) {
// 'errors is empty' -> there were no errors to report
} Prevention
- Only build a CompositeException when at least one Throwable was actually collected.
- Filter nulls from the list before construction.
- Treat an empty aggregation result as success, not as an error to wrap.
When it happens
Trigger: new CompositeException(emptyList()); new CompositeException(listOfNulls); passing a List that contains only a CompositeException whose own exceptions list is empty; building a composite from a stream/collect that filtered everything out.
Common situations: Aggregating errors from a fan-out operation where zero sub-tasks failed (the 'nothing went wrong' case is being incorrectly wrapped); collecting exceptions into a list inside a catch-all loop that may never append; defensive code that always wraps a (possibly empty) list.
Related errors
- count >= 0 expected but it was {}
- Array of size 2 expected but got {}
- Array of size 3 expected but got {}
- Array of size 4 expected but got {}
- Array of size 5 expected but got {}
AI-assisted analysis of ReactiveX/RxJava@a8ab535614 (2026-08-13).
Data as JSON: /api/errors/cc086dd83b36e0ba.
Report an issue: GitHub.