apache/hadoop · error · UnsupportedOperationException

read only iterator

Error message

read only iterator

What it means

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.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java:668

      }

      @Override
      public Path next() {
        final Path result = next;
        try {
          advance();
        } catch (IOException ie) {
          throw new RuntimeException("Can't check existence of " + next, ie);
        }
        if (result == null) {
          throw new NoSuchElementException();
        }
        return result;
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException("read only iterator");
      }

      @Override
      public Iterator<Path> iterator() {
        return this;
      }
    }

    /**
     * Get all of the paths that currently exist in the working directories.
     * @param pathStr the path underneath the roots
     * @param conf the configuration to look up the roots in
     * @return all of the paths that exist under any of the roots
     * @throws IOException
     */
    Iterable<Path> getAllLocalPathsToRead(String pathStr,
        Configuration conf) throws IOException {
      Context ctx = confChanged(conf);

View on GitHub (pinned to 2add963021)

Solutions

  1. Do not call remove(); collect the paths into a List and filter the copy instead
  2. Delete files through FileSystem.delete(Path, boolean) on the specific returned path

Example fix

// before
Iterator<Path> it = alloc.getAllLocalPathsToRead(p, conf).iterator();
it.next();
it.remove();
// after
List<Path> hits = new ArrayList<>();
for (Path path : alloc.getAllLocalPathsToRead(p, conf)) hits.add(path);
fs.delete(hits.get(0), false);   // mutate via FileSystem, never via the iterator
Defensive patterns

Strategy: validation

Try / catch

try {
  it.remove();
} catch (UnsupportedOperationException e) {
  /* read-only iterator: mutate via FileSystem.delete instead */
}

Prevention

When it happens

Trigger: Calling Iterator.remove() on the iterator from LocalDirAllocator#getAllLocalPathsToRead, either directly or indirectly through generic collection utilities/loops that invoke remove() while filtering.

Common situations: Code ported from mutable-collection iteration, custom filtering helpers that call it.remove() unconditionally after a predicate match.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/f958aa0648063447. Report an issue: GitHub.