{"record":{"id":"4f4c85be36d83078","repo":"ReactiveX/RxJava","slug":"read-only-iterator","errorCode":null,"errorMessage":"Read-only iterator.","messagePattern":"Read-only iterator\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/reactivex/rxjava4/internal/operators/flowable/BlockingFlowableLatest.java","lineNumber":114,"sourceCode":"            }\n            return iteratorNotification.isOnNext();\n        }\n\n        @Override\n        public T next() {\n            if (hasNext()) {\n                if (iteratorNotification.isOnNext()) {\n                    T v = iteratorNotification.getValue();\n                    iteratorNotification = null;\n                    return v;\n                }\n            }\n            throw new NoSuchElementException();\n        }\n\n        @Override\n        public void remove() {\n            throw new UnsupportedOperationException(\"Read-only iterator.\");\n        }\n\n    }\n}\n","sourceCodeStart":96,"sourceCodeEnd":119,"githubUrl":"https://github.com/ReactiveX/RxJava/blob/a8ab5356143f37a8f1dd6d76c79191bec5fa343b/src/main/java/io/reactivex/rxjava4/internal/operators/flowable/BlockingFlowableLatest.java#L96-L119","documentation":"Thrown as UnsupportedOperationException('Read-only iterator.') by the Iterator returned by BlockingFlowableLatest when remove() is called. BlockingFlowableLatest exposes only the most recent item from the flowable as a blocking iterator; the underlying sequence is not a mutable collection, so remove() is unsupported by design. The message is more descriptive than the sibling BlockingFlowableIterable iterator but the contract is identical.","triggerScenarios":"Iterating the result of a 'latest'-mode blocking view (e.g. blockingLatest-style access) and invoking iterator.remove() on it — typically from ported List-mutation code or a generic utility that calls remove().","commonSituations":"Adapting List-based cleanup loops to a latest-buffered stream; passing the read-only iterator into a helper that probes remove(); refactoring from a mutable buffer to a reactive latest view.","solutions":["Never call remove() on a latest-buffered iterator; perform filtering upstream with filter() instead.","Materialize the items you want into a mutable ArrayList first, then mutate that list.","Review generic iteration utilities to confirm they skip remove() or are documented as read-only safe.","Switch to a collect-then-process pattern: gather items, then operate on the collected list."],"exampleFix":"// before\nIterator<T> it = latestIterator; // from BlockingFlowableLatest\nwhile (it.hasNext()) {\n    if (stale(it.next())) it.remove(); // throws 'Read-only iterator.'\n}\n\n// after\nList<T> fresh = new ArrayList<>();\nflowable.filter(t -> !stale(t)).blockingSubscribe(fresh::add);","handlingStrategy":"type-guard","validationCode":"// latest-buffered iterators are read-only; collect then mutate.\nList<T> list = new ArrayList<>();\nflowable.filter(t -> !stale(t)).blockingSubscribe(list::add);","typeGuard":"// iterators from BlockingFlowableLatest throw on remove();\n// only iterate, never mutate through them.\nboolean isReadOnly(Iterator<?> it) {\n    return it.getClass().getName().contains(\"BlockingFlowableLatest\");\n}","tryCatchPattern":null,"preventionTips":["Do not call remove() on latest-buffered iterators.","Filter upstream with filter() instead of mutating during iteration.","Keep read-only iterators away from generic mutation utilities."],"tags":["unsupported-operation","iterator","blocking","flowable","latest","rxjava"],"backgroundTag":null,"analyzedSha":"a8ab5356143f37a8f1dd6d76c79191bec5fa343b","analyzedAt":"2026-08-13T23:25:30.069Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}