square/retrofit · error · NullPointerException
scheduler == null
Error message
scheduler == null
What it means
`RxJavaCallAdapterFactory.createWithScheduler(Scheduler)` at RxJavaCallAdapterFactory.java:83 requires a non-null Scheduler because the factory will subscribeOn the supplied scheduler for every stream produced. A null scheduler would NPE later inside RxJava internals with a far less obvious message, so the factory fails fast at construction.
Source
Thrown at retrofit-adapters/rxjava/src/main/java/retrofit2/adapter/rxjava/RxJavaCallAdapterFactory.java:83
* Returns an instance which creates synchronous observables that do not operate on any scheduler
* by default.
*/
public static RxJavaCallAdapterFactory create() {
return new RxJavaCallAdapterFactory(null, false);
}
/** Returns an instance which creates asynchronous observables. */
public static RxJavaCallAdapterFactory createAsync() {
return new RxJavaCallAdapterFactory(null, true);
}
/**
* Returns an instance which creates synchronous observables that {@linkplain
* Observable#subscribeOn(Scheduler) subscribe on} {@code scheduler} by default.
*/
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static RxJavaCallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJavaCallAdapterFactory(scheduler, false);
}
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
private RxJavaCallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {
this.scheduler = scheduler;
this.isAsync = isAsync;
}
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
boolean isSingle = rawType == Single.class;
boolean isCompletable = rawType == Completable.class;
if (rawType != Observable.class && !isSingle && !isCompletable) {View on GitHub (pinned to d0b112dad0)
Solutions
- Pass a concrete Scheduler, e.g. `RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io())`.
- If you do not need a default scheduler, use `create()` (synchronous) or `createAsync()` (async) instead.
- Initialize the scheduler field before constructing the factory.
Example fix
// before
Retrofit r = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(resolveScheduler()))
.build(); // resolveScheduler() may return null -> NPE
// after
Scheduler s = resolveScheduler();
if (s == null) s = rx.schedulers.Schedulers.io();
Retrofit r = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(s))
.build(); Defensive patterns
Strategy: validation
Validate before calling
// Validate before passing to the factory:
Scheduler s = resolveSchedulerFromConfig();
if (s == null) throw new IllegalArgumentException("scheduler config missing; defaulting is disabled");
RxJavaCallAdapterFactory factory = RxJavaCallAdapterFactory.createWithScheduler(s); Try / catch
// Wrap factory construction; default to create() if no scheduler:
RxJavaCallAdapterFactory factory;
try {
factory = RxJavaCallAdapterFactory.createWithScheduler(resolveScheduler());
} catch (NullPointerException e) {
if (e.getMessage().equals("scheduler == null")) {
factory = RxJavaCallAdapterFactory.create(); // synchronous fallback
} else throw e;
} Prevention
- Resolve and validate schedulers from config before factory construction.
- Prefer create()/createAsync() unless you specifically need subscribeOn by default.
- Unit-test your Retrofit wiring module to fail fast on null scheduler.
When it happens
Trigger: Calling `RxJavaCallAdapterFactory.createWithScheduler(null)` when building the Retrofit instance.
Common situations: Passing a Scheduler field that has not been initialized yet; loading a scheduler name from config, resolving to null; or refactoring from create() to createWithScheduler() and forgetting to supply an argument.
Related errors
- scheduler == null
- scheduler == null
- error == null
- response == null
- ${name} return type must be parameterized as ${name}<Foo> or
AI-assisted analysis of square/retrofit@d0b112dad0 (2026-08-04).
Data as JSON: /data/errors/a7486d9cd1f11bc2.json.
Report an issue: GitHub.