ReactiveX/RxJava · warning · UnsupportedOperationException
remove
Error message
remove
What it means
Thrown by the remove() method of the Iterator/Disposable produced by Observable.blockingIterable(). Because the iterable is backed by a streaming Observable (items are produced async and buffered in a queue), there is no backing collection to remove from, so remove() throws UnsupportedOperationException("remove"). The comment notes it overrides a default method for Java 7 compatibility.
Source
Thrown at src/main/java/io/reactivex/rxjava4/internal/operators/observable/BlockingObservableIterable.java:152
@Override
public void onComplete() {
done = true;
signalConsumer();
}
void signalConsumer() {
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
}
@Override // otherwise default method which isn't available in Java 7
public void remove() {
throw new UnsupportedOperationException("remove");
}
@Override
public void dispose() {
DisposableHelper.dispose(this);
signalConsumer(); // Just in case it is currently blocking in hasNext.
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
}
}
View on GitHub (pinned to a8ab535614)
Solutions
- Remove the it.remove() call from your consumption loop; the iterator is read-only.
- Collect consumed values into your own list and drop unwanted ones there rather than removing from the iterator.
- Filter upstream with Observable.filter(...) before blockingIterable() to exclude items.
- If a component requires remove(), delegate through an Iterator whose remove() is a no-op.
Example fix
// before
Iterator<T> it = observable.blockingIterable().iterator();
while (it.hasNext()) { T v = it.next(); if (stale(v)) it.remove(); }
// after
List<T> fresh = new ArrayList<>();
Iterator<T> it = observable.blockingIterable().iterator();
while (it.hasNext()) { T v = it.next(); if (!stale(v)) fresh.add(v); } Defensive patterns
Strategy: validation
Validate before calling
// Read-only iterator: never call remove().
Iterator<T> it = observable.blockingIterable().iterator();
while (it.hasNext()) {
T v = it.next();
// process v; it.remove() is unsupported
} Prevention
- Treat the blockingIterable() iterator as unmodifiable.
- Filter upstream with Observable.filter(...) to exclude items.
- Collect retained values into your own list instead of mutating the iterator.
- Wrap with a no-op remove() forwarder if a dependency requires remove().
When it happens
Trigger: Calling it.remove() on the iterator from observable.blockingIterable().iterator(); a generic drain utility that invokes remove(); legacy collection code repurposed onto a blocking iterable.
Common situations: Reusing imperative drain code that calls remove() to mark consumption; third-party library that calls remove() on any iterator it owns; forgetting blocking iterables are unmodifiable views.
Related errors
AI-assisted analysis of ReactiveX/RxJava@a8ab535614 (2026-08-13).
Data as JSON: /api/errors/eacfa2eb59cf7b71.
Report an issue: GitHub.