{"id":"2d0f5ebf75d59642","repo":"square/retrofit","slug":"scheduler-null-2d0f5e","errorCode":null,"errorMessage":"scheduler == null","messagePattern":"scheduler == null","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"retrofit-adapters/rxjava3/src/main/java/retrofit2/adapter/rxjava3/RxJava3CallAdapterFactory.java","lineNumber":86,"sourceCode":"    return new RxJava3CallAdapterFactory(null, true);\n  }\n\n  /**\n   * Returns an instance which creates synchronous observables that do not operate on any scheduler\n   * by default. Applying {@code subscribeOn(..)} will change the scheduler on which the HTTP calls\n   * are made.\n   */\n  public static RxJava3CallAdapterFactory createSynchronous() {\n    return new RxJava3CallAdapterFactory(null, false);\n  }\n\n  /**\n   * Returns an instance which creates synchronous observables that {@code subscribeOn(..)} the\n   * supplied {@code scheduler} by default.\n   */\n  @SuppressWarnings(\"ConstantConditions\") // Guarding public API nullability.\n  public static RxJava3CallAdapterFactory createWithScheduler(Scheduler scheduler) {\n    if (scheduler == null) throw new NullPointerException(\"scheduler == null\");\n    return new RxJava3CallAdapterFactory(scheduler, false);\n  }\n\n  private final @Nullable Scheduler scheduler;\n  private final boolean isAsync;\n\n  private RxJava3CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {\n    this.scheduler = scheduler;\n    this.isAsync = isAsync;\n  }\n\n  @Override\n  public @Nullable CallAdapter<?, ?> get(\n      Type returnType, Annotation[] annotations, Retrofit retrofit) {\n    Class<?> rawType = getRawType(returnType);\n\n    if (rawType == Completable.class) {\n      // Completable is not parameterized (which is what the rest of this method deals with) so it","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/square/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/rxjava3/src/main/java/retrofit2/adapter/rxjava3/RxJava3CallAdapterFactory.java#L68-L104","documentation":"`RxJava3CallAdapterFactory.createWithScheduler(Scheduler)` at RxJava3CallAdapterFactory.java:86 requires a non-null Scheduler because every stream produced will subscribeOn it. A null scheduler would NPE inside RxJava 3 internals, so the factory fails fast at construction with a clear message.","triggerScenarios":"Calling `RxJava3CallAdapterFactory.createWithScheduler(null)` while building the Retrofit instance.","commonSituations":"Passing an uninitialized Scheduler field; resolving a scheduler from config that returned null; refactoring from create()/createSynchronous() and forgetting the argument.","solutions":["Pass a concrete Scheduler: `RxJava3CallAdapterFactory.createWithScheduler(io.reactivex.rxjava3.core.Schedulers.io())`.","If you do not need a default scheduler, use `create()` (async default) or `createSynchronous()`.","Initialize the scheduler before constructing the factory."],"exampleFix":"// before\nRetrofit r = new Retrofit.Builder()\n    .addCallAdapterFactory(RxJava3CallAdapterFactory.createWithScheduler(resolveScheduler()))\n    .build(); // null -> NPE\n\n// after\nScheduler s = resolveScheduler();\nif (s == null) s = io.reactivex.rxjava3.core.Schedulers.io();\nRetrofit r = new Retrofit.Builder()\n    .addCallAdapterFactory(RxJava3CallAdapterFactory.createWithScheduler(s))\n    .build();","handlingStrategy":"validation","validationCode":"Scheduler s = resolveSchedulerFromConfig();\nif (s == null) throw new IllegalArgumentException(\"scheduler config missing\");\nRxJava3CallAdapterFactory factory = RxJava3CallAdapterFactory.createWithScheduler(s);","typeGuard":null,"tryCatchPattern":"RxJava3CallAdapterFactory factory;\ntry {\n    factory = RxJava3CallAdapterFactory.createWithScheduler(resolveScheduler());\n} catch (NullPointerException e) {\n    if (e.getMessage().equals(\"scheduler == null\")) {\n        factory = RxJava3CallAdapterFactory.create();\n    } else throw e;\n}","preventionTips":["Validate scheduler config before factory construction.","Note RxJava3 defaults to async (create()); use createSynchronous() if you need sync.","Unit-test wiring to catch null schedulers."],"tags":["retrofit","rxjava3","java","null-guard","scheduler","config"],"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-04T19:12:59.096Z","schemaVersion":2}