{"record":{"id":"e1eab5993f015507","repo":"apache/hadoop","slug":"modification-expectedmodification","errorCode":null,"errorMessage":"modification={} != expectedModification = {}","messagePattern":"modification=(.+?) != expectedModification = (.+?)","errorType":"exception","errorClass":"ConcurrentModificationException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/util/LightWeightHashSet.java","lineNumber":552,"sourceCode":"    private int index = -1;\n    /** The next element to return. */\n    private LinkedElement<T> next = nextNonemptyEntry();\n    private LinkedElement<T> current;\n\n    private LinkedElement<T> nextNonemptyEntry() {\n      for (index++; index < entries.length && entries[index] == null; index++);\n      return index < entries.length ? entries[index] : null;\n    }\n\n    @Override\n    public boolean hasNext() {\n      return next != null;\n    }\n\n    @Override\n    public T next() {\n      if (modification != expectedModification) {\n        throw new ConcurrentModificationException(\"modification=\"\n            + modification + \" != expectedModification = \" + expectedModification);\n      }\n      if (next == null) {\n        throw new NoSuchElementException();\n      }\n      current = next;\n      final T e = next.element;\n      // find the next element\n      final LinkedElement<T> n = next.next;\n      next = n != null ? n : nextNonemptyEntry();\n      return e;\n    }\n\n    @Override\n    public void remove() {\n      if (current == null) {\n        throw new NoSuchElementException();\n      }","sourceCodeStart":534,"sourceCodeEnd":570,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/util/LightWeightHashSet.java#L534-L570","documentation":"LightWeightHashSet uses the standard fail-fast iterator pattern: every structural add/remove increments a 'modification' counter, the iterator snapshots it as expectedModification, and next() throws ConcurrentModificationException on mismatch. This fires for single-threaded mutation-during-iteration as well as genuine multi-threaded races - the set itself is not thread-safe.","triggerScenarios":"for-each or explicit Iterator over the set while calling set.add/remove/clear on it (even in the same thread); or another thread mutating without synchronization while this thread iterates.","commonSituations":"Cleanup loops doing set.remove(e) inside iteration; listener/callback registries where iteration triggers re-registration; Namenode tables iterated while RPCs mutate them concurrently.","solutions":["Use iterator.remove() for removal-during-iteration - LightWeightHashSet's iterator supports it and resyncs expectedModification (see 3248 for its failure mode).","Collect doomed elements into a temp list during iteration, then set.removeAll(doomed) afterwards.","Iterate a snapshot: for (T e : new ArrayList<>(set)) - mutations of the original then cannot fail the loop.","For real concurrency, synchronize all access externally or switch to ConcurrentHashMap.newKeySet()."],"exampleFix":"// before\nfor (T e : set) {\n  if (isStale(e)) set.remove(e); // next() throws ConcurrentModificationException\n}\n\n// after - collect-then-remove (no structural change during iteration)\nList<T> doomed = new ArrayList<>();\nfor (T e : set) {\n  if (isStale(e)) doomed.add(e);\n}\nset.removeAll(doomed);","handlingStrategy":"fallback","validationCode":"// snapshot before iterating - original may then be mutated freely\nCollection<T> snapshot = new ArrayList<>(set);\nfor (T e : snapshot) { ... }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call set.add/remove/clear inside a for-each over the same set; use iterator.remove() or collect-then-remove.","For concurrent access, synchronize externally or use ConcurrentHashMap.newKeySet().","Review callback/listener registries for re-entrant mutation during iteration."],"tags":["iteration","fail-fast","concurrent-modification","set"],"backgroundTag":"concurrent-modification-exception","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}