{"record":{"id":"af8148187767b3a8","repo":"lysine-dev/retrofit","slug":"scheduler-null-af8148","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/lysine-dev/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/rxjava3/src/main/java/retrofit2/adapter/rxjava3/RxJava3CallAdapterFactory.java#L68-L104","documentation":"RxJava3CallAdapterFactory.createWithScheduler(Scheduler) builds an adapter factory that subscribeOn's the supplied scheduler by default. Passing null is rejected because the factory would then hold no scheduler to apply; for the no-scheduler case the library provides dedicated factory methods (createSynchronous() for synchronous, createAsync() for asynchronous). It throws NullPointerException ('scheduler == null') behind a ConstantConditions suppression.","triggerScenarios":"Calling RxJava3CallAdapterFactory.createWithScheduler(null), most often when the scheduler is read from DI/configuration/env that was not bound and resolved to null. Thrown immediately at the top of createWithScheduler.","commonSituations":"Reading a Scheduler from a DI graph or config property that resolved to null; conditional scheduler selection that falls through to null; copy-paste of createWithScheduler without choosing the right base factory method; environment differences (e.g. Android main thread scheduler absent in unit tests).","solutions":["If you want no custom scheduler, use the dedicated factory: RxJava3CallAdapterFactory.createSynchronous()() or RxJava3CallAdapterFactory.createAsync().","Otherwise supply a real Scheduler such as Schedulers.io(), Schedulers.computation(), or AndroidSchedulers.mainThread().","Resolve the null at its source (DI binding / config property) rather than passing it through."],"exampleFix":"// before\nRxJavaCallAdapterFactory factory = RxJava3CallAdapterFactory.createWithScheduler(configScheduler);\n// after\nRxJava3CallAdapterFactory factory = configScheduler != null\n    ? RxJava3CallAdapterFactory.createWithScheduler(configScheduler)\n    : RxJava3CallAdapterFactory.createAsync();","handlingStrategy":"validation","validationCode":"Scheduler s = resolveScheduler(); // may be null when unconfigured\nRxJava3CallAdapterFactory factory =\n    s != null\n      ? RxJava3CallAdapterFactory.createWithScheduler(s)\n      : RxJava3CallAdapterFactory.createAsync();","typeGuard":null,"tryCatchPattern":"try {\n  factory = RxJava3CallAdapterFactory.createWithScheduler(s);\n} catch (NullPointerException e) {\n  // s was null; fall back to the async factory\n  factory = RxJava3CallAdapterFactory.createAsync();\n}","preventionTips":["Prefer the no-arg factory methods (createAsync / createSynchronous()) unless you specifically need subscribeOn.","Bind a non-null Scheduler in DI and fail fast at startup if it is missing.","In tests, inject Schedulers.trampoline() rather than null."],"tags":["retrofit","rxjava3","null-safety","java","scheduling","scheduler"],"backgroundTag":null,"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-13T23:49:47.955Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}