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

  1. Only call remove() immediately after a successful next(), once per element
  2. Move the remove() call inside the loop body guarded by the per-element condition
  3. 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

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


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/25e73e3c9b96f58f. Report an issue: GitHub.