pinpoint-apm/pinpoint · error · java.lang.IllegalStateException
IllegalStateException
Error message
IllegalStateException
What it means
Iterator.remove() throws IllegalStateException when lastReturned is null, meaning remove() was called before any next() call, twice in a row, or after the entry was already removed. Each next() must be paired with at most one remove().
Source
Thrown at commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/concurrent/jsr166/ConcurrentWeakHashMap.java:1209
return false;
}
HashEntry<K,V> nextEntry() {
do {
if (nextEntry == null)
throw new NoSuchElementException();
lastReturned = nextEntry;
currentKey = lastReturned.keyRef.get();
advance();
} while (currentKey == null); // Skip GC'd keys
return lastReturned;
}
public void remove() {
if (lastReturned == null)
throw new IllegalStateException();
ConcurrentWeakHashMap.this.remove(currentKey);
lastReturned = null;
}
}
final class KeyIterator
extends HashIterator
implements Iterator<K>, Enumeration<K>
{
public K next() { return super.nextEntry().keyRef.get(); }
public K nextElement() { return super.nextEntry().keyRef.get(); }
}
final class ValueIterator
extends HashIterator
implements Iterator<V>, Enumeration<V>
{
public V next() { return super.nextEntry().value; }View on GitHub (pinned to 744c3d3075)
Solutions
- Only call remove() immediately after a successful next(), once per element
- Move the remove() call inside the loop body guarded by the per-element condition
- Remove via map.remove(key) directly instead of the iterator when state is unclear
Example fix
// before
for (K k : map.keySet()) {
if (expired(k)) map.remove(k);
}
it.remove(); // stray call
// after
Iterator<K> it = map.keySet().iterator();
while (it.hasNext()) {
K k = it.next();
if (expired(k)) { it.remove(); }
} Defensive patterns
Strategy: try-catch
Try / catch
try { it.remove(); } catch (IllegalStateException e) { /* remove without preceding next(): fix loop structure */ } Prevention
- Pair every remove() with exactly one preceding next() call in the same loop iteration
- Never call it.remove() outside the loop body
- Prefer collecting keys then map.removeAll(collected) for bulk cleanup
When it happens
Trigger: it.remove() as the first call on a fresh iterator; calling remove() twice after a single next(); calling remove() after a previous remove() set lastReturned = null.
Common situations: Conditional cleanup loops that call remove() outside the per-element branch; copy-pasted remove logic executed on an unused iterator.
Related errors
- NoSuchElementException
- startTime not recorded
- End index must not be greater than the array length
- IllegalArgumentException
- NullPointerException
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/25e73e3c9b96f58f.
Report an issue: GitHub.