apache/pulsar · error · PulsarClientException.InvalidMessageException
Non-null message is required
Error message
Non-null message is required
What it means
ConsumerBase.validateMessageId(Message) rejects a null Message argument before any acknowledgment-style operation is attempted, throwing InvalidMessageException with 'Non-null message is required'. Ack operations need a real message instance to extract its MessageId, so a null reference is a caller-side programming bug rather than a broker problem.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBase.java:425
break;
}
if (!opBatchReceive.future.isDone()) {
opBatchReceive.future.completeExceptionally(
new PulsarClientException.AlreadyClosedException(
String.format("The consumer which subscribes the topic %s with subscription name %s was"
+ " already closed when cleaning and closing the consumers",
topic, subscription)));
}
}
}
protected abstract Messages<T> internalBatchReceive() throws PulsarClientException;
protected abstract CompletableFuture<Messages<T>> internalBatchReceiveAsync();
private static void validateMessageId(Message<?> message) throws PulsarClientException {
if (message == null) {
throw new PulsarClientException.InvalidMessageException("Non-null message is required");
}
if (message.getMessageId() == null) {
throw new PulsarClientException.InvalidMessageException("Cannot handle message with null messageId");
}
}
private static void validateMessageId(MessageId messageId) throws PulsarClientException {
if (messageId == null) {
throw new PulsarClientException.InvalidMessageException("Cannot handle message with null messageId");
}
}
private static void validateMessageIds(List<MessageId> messageIdList) throws PulsarClientException {
if (messageIdList == null) {
throw new PulsarClientException.InvalidMessageException("Cannot handle messages with null messageIdList");
}
for (MessageId messageId : messageIdList) {
validateMessageId(messageId);View on GitHub (pinned to 820761864e)
Solutions
- Null-check the message before calling acknowledge/reconsumeLater
- Fix the upstream code that produced the null reference (map miss, Optional.get, uninitialized field)
- Use validateMessages/validateMessageIds yourself in tests to fail fast
Example fix
// before
consumer.acknowledge(messageCache.get(id)); // may be null
// after
Message<String> msg = messageCache.get(id);
if (msg != null) {
consumer.acknowledge(msg);
} Defensive patterns
Strategy: validation
Validate before calling
if (message == null) {
throw new IllegalArgumentException("Cannot ack a null message");
}
consumer.acknowledge(message); Type guard
boolean isAckable(Message<?> m) {
return m != null && m.getMessageId() != null;
} Try / catch
try {
consumer.acknowledge(message);
} catch (PulsarClientException.InvalidMessageException e) {
log.warn("Invalid message for ack: {}", e.getMessage());
} Prevention
- Only ack Message objects received directly from this consumer
- Null-check results of cache/map lookups before acking
- Keep Message references immutable from receive() to ack()
When it happens
Trigger: Calling consumer.acknowledge(null), acknowledgeCumulative(null), acknowledgeAsync(null), reconsumeLaterAsync(null, ...), validateMessageIds/validateMessages with a collection containing null — often when message comes from a map lookup or an Optional that was unwrapped unsafely.
Common situations: Caching messages in a Map<MessageId, Message> and acknowledging a missing key; passing the result of a receive() that was short-circuited; processing batched messages where a null element slipped into the list.
Related errors
- Cannot handle message with null messageId
- Cannot handle messages with null messageIdList
- Cannot handle messages with null messages
- isDuplicated cannot accept
- tlsPolicy purpose and policy must not be null
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/13d3e5012083cd9a.
Report an issue: GitHub.