{"record":{"id":"a9847990986c1128","repo":"apache/hadoop","slug":"modification-startmodification","errorCode":null,"errorMessage":"modification={} != startModification = {}","messagePattern":"modification=(.+?) != startModification = (.+?)","errorType":"exception","errorClass":"ConcurrentModificationException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/util/LightWeightLinkedSet.java","lineNumber":253,"sourceCode":"  public Iterator<T> iterator() {\n    return new LinkedSetIterator();\n  }\n\n  private class LinkedSetIterator implements Iterator<T> {\n    /** The starting modification for fail-fast. */\n    private final int startModification = modification;\n    /** The next element to return. */\n    private DoubleLinkedElement<T> next = head;\n\n    @Override\n    public boolean hasNext() {\n      return next != null;\n    }\n\n    @Override\n    public T next() {\n      if (modification != startModification) {\n        throw new ConcurrentModificationException(\"modification=\"\n            + modification + \" != startModification = \" + startModification);\n      }\n      if (next == null) {\n        throw new NoSuchElementException();\n      }\n      final T e = next.element;\n      // find the next element\n      next = next.after;\n      return e;\n    }\n\n    @Override\n    public void remove() {\n      throw new UnsupportedOperationException(\"Remove is not supported.\");\n    }\n  }\n\n  /**","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/util/LightWeightLinkedSet.java#L235-L271","documentation":"LightWeightLinkedSet's iterator snapshots 'modification' as startModification when created; next() throws ConcurrentModificationException whenever any structural add/remove/clear happened since. Identical fail-fast semantics to LightWeightHashSet (3247), but note this iterator offers no remove() at all (3254), so the usual 'iterate and remove' workaround is not available here.","triggerScenarios":"for-each over a LightWeightLinkedSet while the same thread or another thread calls add/remove/clear on it - e.g., evicting expired entries inline.","commonSituations":"Expiry sweeps over insertion-ordered trackers; concurrent RPC threads mutating a shared set; re-entrant code adding during iteration.","solutions":["Collect then mutate: gather elements to remove/add during iteration, apply after the loop (required - iterator has no remove()).","Iterate a copy: new ArrayList<>(set) or set.stream()... when mutation during traversal is expected.","Externalize synchronization or use ConcurrentHashMap.newKeySet() when threads genuinely race."],"exampleFix":"// before\nfor (T e : orderedSet) {\n  if (expired(e)) orderedSet.remove(e); // next() -> ConcurrentModificationException\n}\n\n// after - snapshot iteration (iterator here has no remove())\nfor (T e : new ArrayList<>(orderedSet)) {\n  if (expired(e)) orderedSet.remove(e);\n}","handlingStrategy":"fallback","validationCode":"// this iterator has NO remove() - always iterate a snapshot when mutating\nList<T> snapshot = new ArrayList<>(orderedSet);\nfor (T e : snapshot) { if (expired(e)) orderedSet.remove(e); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Defer all structural changes until after iteration on LightWeightLinkedSet.","Do not port 'iterate and it.remove()' patterns from LightWeightHashSet - unsupported here.","Synchronize or use concurrent collections when multiple threads touch the set."],"tags":["iteration","fail-fast","concurrent-modification","linked-set"],"backgroundTag":"concurrent-modification-exception","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}