I love RxJava, but I have to admit that sometimes it can be quite tough to debug.
I am getting an error
Fatal Exception: java.lang.NullPointerException: Value supplied was null
at io.reactivex.internal.operators.single.SingleOnErrorReturn$OnErrorReturn.onError(SingleOnErrorReturn.java:66)
at io.reactivex.internal.operators.single.SingleDelayWithCompletable$OtherObserver.onError(SingleDelayWithCompletable.java:64)
at io.reactivex.internal.operators.completable.CompletableFromSingle$CompletableFromSingleObserver.onError(CompletableFromSingle.java:41)
at io.reactivex.internal.operators.single.SingleOnErrorReturn$OnErrorReturn.onError(SingleOnErrorReturn.java:68)
at io.reactivex.internal.observers.ResumeSingleObserver.onError(ResumeSingleObserver.java:51)
at io.reactivex.internal.disposables.EmptyDisposable.error(EmptyDisposable.java:78)
at io.reactivex.internal.operators.single.SingleError.subscribeActual(SingleError.java:42)
at io.reactivex.Single.subscribe(Single.java:3666)
at io.reactivex.internal.operators.single.SingleResumeNext$ResumeMainSingleObserver.onError(SingleResumeNext.java:80)
at io.reactivex.internal.operators.single.SingleMap$MapSingleObserver.onError(SingleMap.java:69)
at io.reactivex.internal.operators.single.SingleMap$MapSingleObserver.onError(SingleMap.java:69)
at io.reactivex.internal.operators.observable.ObservableToListSingle$ToListObserver.onError(ObservableToListSingle.java:104)
at io.reactivex.observers.SerializedObserver.onError(SerializedObserver.java:153)
at io.reactivex.internal.operators.observable.ObservableConcatMap$SourceObserver.onError(ObservableConcatMap.java:142)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.tryOnError(ObservableCreate.java:84)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onError(ObservableCreate.java:72)
at it.mypackage.data.source.aws.LegDataSourceLegsListener.onFailure(LegADataSource.java:760)
at com.apollographql.apollo.GraphQLCall$Callback.onNetworkError(GraphQLCall.java:135)
at com.apollographql.apollo.internal.RealAppSyncCall$1.onFailure(RealAppSyncCall.java:259)
at com.apollographql.apollo.internal.interceptor.ApolloCacheInterceptor$1$1.onFailure(ApolloCacheInterceptor.java:108)
at com.apollographql.apollo.internal.interceptor.ApolloParseInterceptor$1.onFailure(ApolloParseInterceptor.java:94)
at com.apollographql.apollo.internal.interceptor.ApolloServerInterceptor$1$1.onFailure(ApolloServerInterceptor.java:105)
at okhttp3.RealCall$AsyncCall.run(RealCall.kt:146)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
The error seems to come from this snippet:
@Override
public void onFailure(@Nonnull ApolloException e) {
if (!emitter.isDisposed()) {
emitter.onError(e); // here's the problem
}
}
Now the thing is that ApolloException
is not null, also checking the implementation I can tell that it shouldn't be possible to have null as argument of the onFailure
.
callBack.onFailure(new ApolloNetworkException("Failed to execute http call", e));
So, where does that error come from?
Any idea?
NOTE: I am using RxJava2, version 2.3.4
The NullPointerException
is coming specifically from SingleOnErrorReturn$OnErrorReturn.OnError
:
public void onError(Throwable e) {
T v;
if (valueSupplier != null) {
try {
v = valueSupplier.apply(e);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
observer.onError(new CompositeException(e, ex));
return;
}
} else {
v = value;
}
if (v == null) {
NullPointerException npe = new NullPointerException("Value supplied was null"); // This is the exception you're hitting
npe.initCause(e);
observer.onError(npe);
return;
}
The v
it is complaining about is the value
that was actually passed to the onErrorReturn(T value)
operator. The value
passed is null
, which is not allowed.
So I would look for an onErrorReturn
operator downstream from t.mypackage.data.source.aws.LegDataSourceLegsListener.onFailure
, which is taking a null
value. It looks like it will appear right after a .delaySubscription(Completable)
operator, based on the stack trace.