apache/pulsar · error · java.lang.IllegalStateException
Empty message batch
Error message
Empty message batch
What it means
Thrown by MessagesV5.lastId() when the batch contains no messages. The library cannot return a meaningful last message id from an empty collection, so it fails fast with IllegalStateException. Callers must check size/emptiness before querying batch boundary ids.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MessagesV5.java:46
* Simple implementation of Messages wrapping a list of Message instances.
*/
final class MessagesV5<T> implements Messages<T> {
private final List<Message<T>> messages;
MessagesV5(List<Message<T>> messages) {
this.messages = messages;
}
@Override
public int count() {
return messages.size();
}
@Override
public MessageId lastId() {
if (messages.isEmpty()) {
throw new IllegalStateException("Empty message batch");
}
return messages.get((messages.size() - 1)).id();
}
@Override
public Iterator<Message<T>> iterator() {
return messages.iterator();
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Check messages.isEmpty() (or size() > 0) before calling lastId()
- Guard by tracking whether any messages were received and skip lastId() when none were
- If lastId is used for cumulative acks, only ack when the batch is non-empty
Example fix
// before
MessageId last = batch.lastId();
// after
if (batch.size() > 0) {
MessageId last = batch.lastId();
} Defensive patterns
Strategy: validation
Validate before calling
if (batch == null || batch.size() == 0) { skipLastId(); } else { batch.lastId(); } Prevention
- Always check batch size before boundary-id queries
- Track received-message counts in the consume loop
When it happens
Trigger: Calling lastId() on a MessagesV5 instance built with no messages, e.g. after filtering out every message or constructing an empty MessagesV5 via its builder/factory.
Common situations: A consumer received no messages but code still tries to inspect the batch's last id for cursor/cumulative-ack bookkeeping; a loop that drains a queue into a batch ends up empty.
Related errors
- Try to reserve/release memory failed, the param memorySize i
- Failed to decode message from topic ${topic} with schemaId $
- Cannot set resourceTypes when shareConfigured() has already
- Cannot use shareConfigured() when resourceTypes has already
- Unknown resource type:
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b83d5b6abd875950.
Report an issue: GitHub.