ReactiveX/RxJava · error · IllegalArgumentException
unsafeCreate(Maybe) should be upgraded
Error message
unsafeCreate(Maybe) should be upgraded
What it means
Thrown by Maybe.unsafeCreate when the argument is already a Maybe instance. unsafeCreate is meant to bridge foreign MaybeSource implementations; wrapping a real Maybe is redundant and almost always a migration remnant. Note the NPE check runs after this guard, so a null Maybe is fine but a non-null Maybe triggers this error.
Source
Thrown at src/main/java/io/reactivex/rxjava4/core/Maybe.java:1533
* any safeguards by using a callback that is called with a {@link MaybeObserver}.
* <p>
* <img width="640" height="262" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.unsafeCreate.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code unsafeCreate} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
* @param <T> the value type
* @param onSubscribe the function that is called with the subscribing {@code MaybeObserver}
* @return the new {@code Maybe} instance
* @throws IllegalArgumentException if {@code onSubscribe} is a {@code Maybe}
* @throws NullPointerException if {@code onSubscribe} is {@code null}
*/
@CheckReturnValue
@NonNull
@SchedulerSupport(SchedulerSupport.NONE)
public static <@NonNull T> Maybe<T> unsafeCreate(@NonNull MaybeSource<T> onSubscribe) {
if (onSubscribe instanceof Maybe) {
throw new IllegalArgumentException("unsafeCreate(Maybe) should be upgraded");
}
Objects.requireNonNull(onSubscribe, "onSubscribe is null");
return RxJavaPlugins.onAssembly(new MaybeUnsafeCreate<>(onSubscribe));
}
/**
* Constructs a {@code Maybe} that creates a dependent resource object which is disposed of when the
* generated {@link MaybeSource} terminates or the downstream calls dispose().
* <p>
* <img width="640" height="378" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Maybe.using.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code using} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @param <T> the element type of the generated {@code MaybeSource}
* @param <D> the type of the resource associated with the output sequence
* @param resourceSupplierView on GitHub (pinned to a8ab535614)
Solutions
- Use the Maybe directly instead of wrapping: drop unsafeCreate.
- If you need to hide identity, call source.hide().
- Restrict the call site so unsafeCreate only receives non-Maybe MaybeSource instances.
Example fix
// before Maybe<String> src = loadMaybe(); Maybe<String> wrapped = Maybe.unsafeCreate(src); // after Maybe<String> wrapped = src; // or: Maybe<String> hidden = src.hide();
Defensive patterns
Strategy: type-guard
Validate before calling
MaybeSource<T> source = loadSource();
if (source instanceof Maybe) {
// unsafeCreate would throw; use directly or hide()
return;
} Type guard
static <T> boolean needsUnsafeCreate(MaybeSource<T> s) {
return s != null && !(s instanceof Maybe);
} Try / catch
try {
return Maybe.unsafeCreate(source);
} catch (IllegalArgumentException e) {
return source instanceof Maybe ? (Maybe<T>) source : Maybe.error(e);
} Prevention
- Use unsafeCreate only for foreign MaybeSource implementations, not for Maybe.
- Prefer hide() when you need to obscure Maybe identity.
- Type-guard generic adapters that accept MaybeSource.
When it happens
Trigger: Calling Maybe.unsafeCreate(someMaybe) where the runtime type is Maybe. Common when an upstream operator or helper returns Maybe and the caller unconditionally wraps it.
Common situations: RxJava 1.x porting where Observable.unsafeCreate patterns were common; generic adapters that wrap any source without checking identity.
Related errors
- Use of unsafeCreate(Completable)!
- unsafeCreate(Single) should be upgraded
- count >= 0 required but it was {}
- count >= 0 required but it was {}
- count >= 0 required but it was {}
AI-assisted analysis of ReactiveX/RxJava@a8ab535614 (2026-08-13).
Data as JSON: /api/errors/f1e7480b04584f50.
Report an issue: GitHub.