ReactiveX/RxJava · error · IllegalArgumentException
Array of size 3 expected but got {}
Error message
Array of size 3 expected but got {} What it means
Thrown by Array3Func.apply(Object[]) when the array length is not exactly 3. Array3Func adapts a Function3 (3-ary) to Function<Object[],R>, used internally by 3-way zip/combineLatest fan-in. The arity of the array must equal the number of sources the function expects.
Source
Thrown at src/main/java/io/reactivex/rxjava4/internal/functions/Functions.java:481
record Array2Func<T1, T2, R>(BiFunction<? super T1, ? super T2, ? extends R> f) implements Function<Object[], R> {
@SuppressWarnings("unchecked")
@Override
public R apply(Object[] a) throws Throwable {
if (a.length != 2) {
throw new IllegalArgumentException("Array of size 2 expected but got " + a.length);
}
return f.apply((T1) a[0], (T2) a[1]);
}
}
record Array3Func<T1, T2, T3, R>(Function3<T1, T2, T3, R> f) implements Function<Object[], R> {
@SuppressWarnings("unchecked")
@Override
public R apply(Object[] a) throws Throwable {
if (a.length != 3) {
throw new IllegalArgumentException("Array of size 3 expected but got " + a.length);
}
return f.apply((T1) a[0], (T2) a[1], (T3) a[2]);
}
}
record Array4Func<T1, T2, T3, T4, R>(Function4<T1, T2, T3, T4, R> f) implements Function<Object[], R> {
@SuppressWarnings("unchecked")
@Override
public R apply(Object[] a) throws Throwable {
if (a.length != 4) {
throw new IllegalArgumentException("Array of size 4 expected but got " + a.length);
}
return f.apply((T1) a[0], (T2) a[1], (T3) a[2], (T4) a[3]);
}
}
static final class Array5Func<T1, T2, T3, T4, T5, R> implements Function<Object[], R> {View on GitHub (pinned to a8ab535614)
Solutions
- Make the Object[] length exactly 3 when invoking a 3-arity adapter; fix the code that assembles the array.
- Use the public 3-source zip/combineLatest overloads, which manage arity correctly, instead of manual adapters.
- Add a test asserting the array passed to a Function3 adapter has length 3.
- Derive array length from the live source count, never from a separate hardcoded literal.
Example fix
// before
Function<Object[], R> f = Functions.array3Func(fn3);
R r = f.apply(new Object[]{ a, b }); // length 2 -> throws
// after
Function<Object[], R> f = Functions.array3Func(fn3);
R r = f.apply(new Object[]{ a, b, c }); // length 3 matches arity Defensive patterns
Strategy: validation
Validate before calling
assert args.length == 3 : "3-arity adapter requires length-3 array"; // couple the array size to the number of combined sources
Try / catch
try {
R r = array3Fn.apply(args);
} catch (IllegalArgumentException e) {
// re-align source count with the 3-arity function
} Prevention
- Use public 3-source zip/combineLatest overloads to avoid manual arity management.
- When refactoring a fan-in, update both the adapter arity and the array together.
- Test with arrays of length 2, 3, and 4 to lock the contract.
When it happens
Trigger: A 3-arity array function adapter receives an Object[] whose length != 3. Reachable mainly from custom/test operator code that mismatches the number of combined sources against the adapter arity.
Common situations: Building a 3-way combine/zip manually with an array assembled from a variable number of sources; copy-pasting a 2-source adapter pattern into a 3-source scenario without updating the array construction; reflective source assembly.
Related errors
- Array of size 2 expected but got {}
- Array of size 4 expected but got {}
- Array of size 5 expected but got {}
- Array of size 6 expected but got {}
- Array of size 7 expected but got {}
AI-assisted analysis of ReactiveX/RxJava@a8ab535614 (2026-08-13).
Data as JSON: /api/errors/7f29cbc8b7ca997b.
Report an issue: GitHub.