{"record":{"id":"0b84212ab302bb26","repo":"apache/pulsar","slug":"cannot-handle-messages-with-null-messageidlist","errorCode":null,"errorMessage":"Cannot handle messages with null messageIdList","messagePattern":"Cannot handle messages with null messageIdList","errorType":"exception","errorClass":"PulsarClientException.InvalidMessageException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBase.java","lineNumber":440,"sourceCode":"\n    private static void validateMessageId(Message<?> message) throws PulsarClientException {\n        if (message == null) {\n            throw new PulsarClientException.InvalidMessageException(\"Non-null message is required\");\n        }\n        if (message.getMessageId() == null) {\n            throw new PulsarClientException.InvalidMessageException(\"Cannot handle message with null messageId\");\n        }\n    }\n\n    private static void validateMessageId(MessageId messageId) throws PulsarClientException {\n        if (messageId == null) {\n            throw new PulsarClientException.InvalidMessageException(\"Cannot handle message with null messageId\");\n        }\n    }\n\n    private static void validateMessageIds(List<MessageId> messageIdList) throws PulsarClientException {\n        if (messageIdList == null) {\n            throw new PulsarClientException.InvalidMessageException(\"Cannot handle messages with null messageIdList\");\n        }\n        for (MessageId messageId : messageIdList) {\n            validateMessageId(messageId);\n        }\n    }\n\n    private static void validateMessages(Messages<?> messages) throws PulsarClientException {\n        if (messages == null) {\n            throw new PulsarClientException.InvalidMessageException(\"Cannot handle messages with null messages\");\n        }\n        for (Message<?> message : messages) {\n            validateMessageId(message);\n        }\n    }\n    @Override\n    public void acknowledge(Message<?> message) throws PulsarClientException {\n        validateMessageId(message);\n        acknowledge(message.getMessageId());","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBase.java#L422-L458","documentation":"validateMessageIds(List<MessageId>) first rejects a null list with InvalidMessageException 'Cannot handle messages with null messageIdList', then validates each element. Multi-message acknowledgment (acknowledge(List<MessageId>) and transactional acks via doAcknowledgeWithTxn) requires a concrete, non-empty-capable list because the broker needs the set of IDs to ack.","triggerScenarios":"Calling consumer.acknowledge((List<MessageId>) null) or acknowledgeAsync with a null list — usually when the list was built conditionally and never initialized, or a method parameter was forwarded without checking.","commonSituations":"Aggregating IDs for batch acking where the aggregation step returned null instead of an empty list; refactoring from single-ack to batch-ack while keeping old nullable variables.","solutions":["Initialize ID collections as empty lists (Collections.emptyList()) instead of null","Null-check the list before calling acknowledge(List<MessageId>)","Guard the batch-ack behind a isEmpty()/!= null check"],"exampleFix":"// before\nList<MessageId> ids = aggregator.getIds(); // may be null\nconsumer.acknowledge(ids);\n// after\nList<MessageId> ids = aggregator.getIds();\nif (ids != null && !ids.isEmpty()) {\n    consumer.acknowledge(ids);\n}","handlingStrategy":"validation","validationCode":"if (idList == null || idList.isEmpty()) {\n    return; // nothing to ack\n}","typeGuard":"boolean isAckableList(List<MessageId> ids) {\n    return ids != null && !ids.isEmpty() && ids.stream().allMatch(java.util.Objects::nonNull);\n}","tryCatchPattern":"try {\n    consumer.acknowledge(messageIdList);\n} catch (PulsarClientException.InvalidMessageException e) {\n    log.warn(\"Invalid messageIdList: {}\", e.getMessage());\n}","preventionTips":["Initialize ID lists as empty collections, never null","Return Collections.emptyList() instead of null from aggregation methods","Validate list contents with a shared guard before multi-ack"],"tags":["pulsar","acknowledgment","null-check","batch"],"backgroundTag":"null-message-id","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}