ReactiveX/RxJava · error · UnsupportedOperationException
The class {} does not support isDisposed
Error message
The class {} does not support isDisposed What it means
Thrown by the default isDisposed() implementation inherited via the DisposableOnly interface. DisposableOnly extends Disposable but explicitly opts out of implementing isDisposed(), because for many disposable resources the disposed state is either never observable or never queried in practice. Any code that calls isDisposed() on an instance typed only as DisposableOnly/Disposable will hit this UnsupportedOperationException at runtime — the compiler will not warn because the method exists on the interface.
Source
Thrown at src/main/java/io/reactivex/rxjava4/internal/disposables/DisposableOnly.java:28
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the specific language governing permissions and limitations under the License.
*/
package io.reactivex.rxjava4.internal.disposables;
import io.reactivex.rxjava4.disposables.Disposable;
/**
* An extension to {@link Disposable} that allows not
* implementing the {@link Disposable#isDisposed()} as it
* is practically never needed or cannot be observed anyways.
* @since 4.0.0
*/
public interface DisposableOnly extends Disposable {
@Override
default boolean isDisposed() {
throw new UnsupportedOperationException("The class " + this.getClass() + " does not support isDisposed");
}
}
View on GitHub (pinned to a8ab535614)
Solutions
- Do not call isDisposed() on DisposableOnly instances; track disposal yourself (e.g. via a boolean flag set in dispose()).
- Narrow the type so callers cannot reach isDisposed(), or override isDisposed() in the implementing class if the state is actually observable.
- In shared helpers, guard with an instanceof/type check (see defense) before invoking isDisposed().
- If you genuinely need disposed-state observation, use a full Disposable implementation (e.g. via a ref-counted or AtomicBoolean-based disposable) instead of DisposableOnly.
Example fix
// before
DisposableOnly d = createResource();
if (d.isDisposed()) { ... } // throws UnsupportedOperationException
// after
DisposableOnly d = createResource();
// track disposal yourself; never call isDisposed() on DisposableOnly Defensive patterns
Strategy: type-guard
Validate before calling
boolean safeIsDisposed(Disposable d) {
if (d instanceof DisposableOnly && !overridesIsDisposed(d)) {
return false; // state not observable; assume not disposed or track externally
}
return d.isDisposed();
} Type guard
boolean isFullyObservable(Disposable d) {
// DisposableOnly opts out of isDisposed by default; treat such instances as non-queryable.
return !(d instanceof DisposableOnly);
} Prevention
- Never call isDisposed() on DisposableOnly-typed references; track a local disposed flag instead.
- In shared resource utilities, type-check for DisposableOnly before probing isDisposed().
- If you need observable disposal, implement a full Disposable rather than DisposableOnly.
When it happens
Trigger: Calling isDisposed() on an object whose static or declared type is DisposableOnly (or a class implementing it without overriding isDisposed). Common when a resource is stored in a Disposable-typed field or passed to a helper that defensively calls isDisposed().
Common situations: Generic resource-tracking utilities that call isDisposed() on every Disposable; testing helpers that assert disposed state; migrating from RxJava 2/3 where isDisposed() was always implemented; using CompositeDisposable-like bookkeeping that probes state.
Related errors
AI-assisted analysis of ReactiveX/RxJava@a8ab535614 (2026-08-13).
Data as JSON: /api/errors/c050f781ac73b727.
Report an issue: GitHub.