{"record":{"id":"69328b9145b0499d","repo":"ReactiveX/RxJava","slug":"read-only-iterator-69328b","errorCode":null,"errorMessage":"Read-only iterator.","messagePattern":"Read-only iterator\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"warning","filePath":"src/main/java/io/reactivex/rxjava4/internal/operators/observable/BlockingObservableLatest.java","lineNumber":111,"sourceCode":"                    throw ExceptionHelper.wrapOrThrow(n.getError());\n                }\n            }\n            return iteratorNotification.isOnNext();\n        }\n\n        @Override\n        public T next() {\n            if (hasNext()) {\n                T v = iteratorNotification.getValue();\n                iteratorNotification = null;\n                return v;\n            }\n            throw new NoSuchElementException();\n        }\n\n        @Override\n        public void remove() {\n            throw new UnsupportedOperationException(\"Read-only iterator.\");\n        }\n    }\n}\n","sourceCodeStart":93,"sourceCodeEnd":115,"githubUrl":"https://github.com/ReactiveX/RxJava/blob/a8ab5356143f37a8f1dd6d76c79191bec5fa343b/src/main/java/io/reactivex/rxjava4/internal/operators/observable/BlockingObservableLatest.java#L93-L115","documentation":"Thrown by Iterator.remove() on the iterator returned from Observable.blockingLatest(). The iterator surfaces the most recent Notification from a push source and is read-only by contract, so remove() always throws UnsupportedOperationException(\"Read-only iterator.\"). There is no mutable backing collection to alter.","triggerScenarios":"Calling it.remove() on the iterator from observable.blockingLatest().iterator(); a generic cleanup routine invoking remove(); reusing collection-based drain code.","commonSituations":"Imperative drain loops ported from List iteration that included remove(); libraries that call remove() on consumed iterators; misunderstanding blockingLatest() as a mutable buffer.","solutions":["Drop the it.remove() call; blockingLatest() iterators are read-only.","Filter upstream with Observable.filter(...) to remove unwanted items before blocking iteration.","Accumulate the items you want to keep in a separate list rather than mutating the iterator.","Wrap with a forwarding Iterator whose remove() is a no-op if a dependency mandates remove()."],"exampleFix":"// before\nIterator<T> it = observable.blockingLatest().iterator();\nwhile (it.hasNext()) { T v = it.next(); if (skip(v)) it.remove(); }\n// after\nIterator<T> it = observable.blockingLatest().iterator();\nwhile (it.hasNext()) { T v = it.next(); if (!skip(v)) { /* keep v */ } }","handlingStrategy":"validation","validationCode":"// Read-only iterator: never call remove().\nIterator<T> it = observable.blockingLatest().iterator();\nwhile (it.hasNext()) {\n    T v = it.next();\n    // process v; it.remove() is unsupported\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Recognize blockingLatest() iterators as read-only.","Filter upstream with Observable.filter(...) instead of removing.","Keep a separate mutable list of retained items.","Forward through a no-op remove() wrapper if a dependency calls remove()."],"tags":["rxjava","iterator","unsupported-operation","blocking","observable"],"backgroundTag":null,"analyzedSha":"a8ab5356143f37a8f1dd6d76c79191bec5fa343b","analyzedAt":"2026-08-13T23:25:30.069Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}