apache/hadoop · error · UnsupportedOperationException

Remove is not supported.

Error message

Remove is not supported.

What it means

Unlike LightWeightHashSet's iterator (which implements remove), LightWeightLinkedSet's iterator.remove() unconditionally throws UnsupportedOperationException. Removing through the iterator would need to unlink nodes from both the hash chain and the insertion-order doubly-linked list, which the implementation deliberately does not support.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/util/LightWeightLinkedSet.java:267

    @Override
    public T next() {
      if (modification != startModification) {
        throw new ConcurrentModificationException("modification="
            + modification + " != startModification = " + startModification);
      }
      if (next == null) {
        throw new NoSuchElementException();
      }
      final T e = next.element;
      // find the next element
      next = next.after;
      return e;
    }

    @Override
    public void remove() {
      throw new UnsupportedOperationException("Remove is not supported.");
    }
  }

  /**
   * Clear the set. Resize it to the original capacity.
   */
  @Override
  public void clear() {
    super.clear();
    this.head = null;
    this.tail = null;
    this.resetBookmark();
  }

  /**
   * Returns a new iterator starting at the bookmarked element.
   *
   * @return the iterator to the bookmarked element.

View on GitHub (pinned to 2add963021)

Solutions

  1. Collect elements to remove into a temp list during iteration, then call set.removeAll(temp) (or set.remove(e)) afterwards.
  2. Iterate a copy and remove from the original (see 3253 example).
  3. If iterator-level removal is a hard requirement, use LightWeightHashSet where insertion order does not matter.

Example fix

// before
for (Iterator<T> it = set.iterator(); it.hasNext(); ) {
  if (stale(it.next())) it.remove(); // UnsupportedOperationException
}

// after - defer removals
List<T> doomed = new ArrayList<>();
for (T e : set) {
  if (stale(e)) doomed.add(e);
}
set.removeAll(doomed);
Defensive patterns

Strategy: fallback

Validate before calling

// collect-then-remove is the only safe removal-during-iteration pattern here
List<T> doomed = new ArrayList<>();
for (T e : set) { if (stale(e)) doomed.add(e); }
set.removeAll(doomed);

Prevention

When it happens

Trigger: Calling it.remove() inside any loop over a LightWeightLinkedSet - including code ported from LightWeightHashSet or HashSet where iterator removal worked.

Common situations: Shared cleanup utilities written against Iterator.remove(); refactors between the two light-weight collections; generic filtering code that assumes Iterator's optional remove() exists.

Related errors


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