{"record":{"id":"f958aa0648063447","repo":"apache/hadoop","slug":"read-only-iterator","errorCode":null,"errorMessage":"read only iterator","messagePattern":"read only iterator","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java","lineNumber":668,"sourceCode":"      }\n\n      @Override\n      public Path next() {\n        final Path result = next;\n        try {\n          advance();\n        } catch (IOException ie) {\n          throw new RuntimeException(\"Can't check existence of \" + next, ie);\n        }\n        if (result == null) {\n          throw new NoSuchElementException();\n        }\n        return result;\n      }\n\n      @Override\n      public void remove() {\n        throw new UnsupportedOperationException(\"read only iterator\");\n      }\n\n      @Override\n      public Iterator<Path> iterator() {\n        return this;\n      }\n    }\n\n    /**\n     * Get all of the paths that currently exist in the working directories.\n     * @param pathStr the path underneath the roots\n     * @param conf the configuration to look up the roots in\n     * @return all of the paths that exist under any of the roots\n     * @throws IOException\n     */\n    Iterable<Path> getAllLocalPathsToRead(String pathStr,\n        Configuration conf) throws IOException {\n      Context ctx = confChanged(conf);","sourceCodeStart":650,"sourceCodeEnd":686,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java#L650-L686","documentation":"PathIterator returned by LocalDirAllocator.getAllLocalPathsToRead() is a read-only Iterator<Path>; its remove() is hard-coded to throw UnsupportedOperationException because the iterator only enumerates paths that exist across the configured working directories and supports no mutation.","triggerScenarios":"Calling Iterator.remove() on the iterator from LocalDirAllocator#getAllLocalPathsToRead, either directly or indirectly through generic collection utilities/loops that invoke remove() while filtering.","commonSituations":"Code ported from mutable-collection iteration, custom filtering helpers that call it.remove() unconditionally after a predicate match.","solutions":["Do not call remove(); collect the paths into a List and filter the copy instead","Delete files through FileSystem.delete(Path, boolean) on the specific returned path"],"exampleFix":"// before\nIterator<Path> it = alloc.getAllLocalPathsToRead(p, conf).iterator();\nit.next();\nit.remove();\n// after\nList<Path> hits = new ArrayList<>();\nfor (Path path : alloc.getAllLocalPathsToRead(p, conf)) hits.add(path);\nfs.delete(hits.get(0), false);   // mutate via FileSystem, never via the iterator","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  it.remove();\n} catch (UnsupportedOperationException e) {\n  /* read-only iterator: mutate via FileSystem.delete instead */\n}","preventionTips":["Treat LocalDirAllocator iterators as read-only","Collect results into a List when you need to filter or mutate","Delete files only via FileSystem.delete(Path, boolean)"],"tags":["iterator","unsupported-operation","local-dirs"],"backgroundTag":"unsupported-operation-exception","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}