apache/pulsar · error · NoSuchElementException
NoSuchElementException
Error message
NoSuchElementException
What it means
GrowableArrayBlockingQueue.remove (BlockingQueue contract): the queue was empty at removal time, so there is no element to remove and NoSuchElementException is thrown — the standard j.u.c. behavior for remove() on an empty queue.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/collections/GrowableArrayBlockingQueue.java:79
public GrowableArrayBlockingQueue() {
this(64);
}
@SuppressWarnings("unchecked")
public GrowableArrayBlockingQueue(int initialCapacity) {
headIndex.value = 0;
tailIndex.value = 0;
int capacity = io.netty.util.internal.MathUtil.findNextPositivePowerOfTwo(initialCapacity);
data = (T[]) new Object[capacity];
}
@Override
public T remove() {
T item = poll();
if (item == null) {
throw new NoSuchElementException();
}
return item;
}
@Override
public T poll() {
return pollIf(v -> true);
}
public T pollIf(Predicate<T> predicate) {
headLock.lock();
try {
if (SIZE_UPDATER.get(this) > 0) {
T item = data[headIndex.value];
if (!predicate.test(item)) {
return null;
}View on GitHub (pinned to 820761864e)
Solutions
- Check size/emptiness before calling remove, or use poll() which returns null
Example fix
// before
T item = queue.remove();
// after
T item = queue.poll();
if (item == null) {
return; // queue empty
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!queue.isEmpty()) { T item = queue.remove(); ... }
// or preferably: T item = queue.poll(); Try / catch
try {
T item = queue.remove();
} catch (NoSuchElementException e) {
// queue was empty
} Prevention
- Prefer poll()/peek() over remove()/element() under concurrency
- Never assume isEmpty() then remove() is atomic
- Handle empty-queue drains explicitly
When it happens
Trigger: Calling remove() on an empty queue (no elements ever added, or all elements already consumed).
Common situations: Draining a queue in a loop without checking isEmpty, or race where another consumer took the last element between isEmpty and remove.
Related errors
- Unable to determine latest version since broker version map
- ${key} already exists in the dynamicConfigurationMap
- Topic factory failed to create topic
- No more range can assigned to new consumer, assigned consume
- Range conflict with consumer ${conflictingConsumer}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a58a2b4a7aa576c1.
Report an issue: GitHub.