{"record":{"id":"b83d5b6abd875950","repo":"apache/pulsar","slug":"empty-message-batch","errorCode":null,"errorMessage":"Empty message batch","messagePattern":"Empty message batch","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MessagesV5.java","lineNumber":46,"sourceCode":" * Simple implementation of Messages wrapping a list of Message instances.\n */\nfinal class MessagesV5<T> implements Messages<T> {\n\n    private final List<Message<T>> messages;\n\n    MessagesV5(List<Message<T>> messages) {\n        this.messages = messages;\n    }\n\n    @Override\n    public int count() {\n        return messages.size();\n    }\n\n    @Override\n    public MessageId lastId() {\n        if (messages.isEmpty()) {\n            throw new IllegalStateException(\"Empty message batch\");\n        }\n        return messages.get((messages.size() - 1)).id();\n    }\n\n    @Override\n    public Iterator<Message<T>> iterator() {\n        return messages.iterator();\n    }\n}\n","sourceCodeStart":28,"sourceCodeEnd":56,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MessagesV5.java#L28-L56","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nMessageId last = batch.lastId();\n// after\nif (batch.size() > 0) {\n    MessageId last = batch.lastId();\n}","handlingStrategy":"validation","validationCode":"if (batch == null || batch.size() == 0) { skipLastId(); } else { batch.lastId(); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always check batch size before boundary-id queries","Track received-message counts in the consume loop"],"tags":["pulsar","client","message-batch","empty-collection"],"backgroundTag":"empty-message-batch","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}