Skip to content

[Bug][Client] hasMessageAvailable() throws UnsupportedOperationException when consumer created via newConsumer().subscribe() before any message is read #25837

@jaro-herod

Description

@jaro-herod

Search before reporting

  • I searched in the issues and found nothing similar.

Read release policy

  • I understand that unsupported versions don't get bug fixes. I will attempt to reproduce the issue on a supported version of Pulsar client and Pulsar broker.

User environment

Java Client Library :
┌─────────┬───────────────────────────┐
│ Version │ Bug present? │
├─────────┼───────────────────────────┤
│ 4.1.1 │ ✅ yes │
├─────────┼───────────────────────────┤
│ 4.1.2 │ ✅ yes │
├─────────┼───────────────────────────┤
│ 4.1.3 │ ✅ yes │
├─────────┼───────────────────────────┤
│ 4.2.0 │ ✅ yes │
├─────────┼───────────────────────────┤
│ 4.2.1 │ ✅ yes │
├─────────┼───────────────────────────┤
│ master │ ✅ yes (as of 2026-05-20) │
└─────────┴───────────────────────────┘

Issue Description

Calling consumer.hasMessageAvailable() (or the async variant) on a consumer created via PulsarClient.newConsumer().subscribe() throws UnsupportedOperationException: Unknown MessageId type: null if called before any message has been dequeued.

The exception propagates from MessageIdAdv.compareTo() when ConsumerImpl.hasMoreMessages() is called with a null startMessageId.

Error messages

java.lang.UnsupportedOperationException: Unknown MessageId type: null
     at org.apache.pulsar.client.api.MessageIdAdv.compareTo(MessageIdAdv.java:106)
     at org.apache.pulsar.client.api.MessageIdAdv.compareTo(MessageIdAdv.java:29)
     at org.apache.pulsar.client.impl.ConsumerImpl.hasMoreMessages(ConsumerImpl.java:2805)
     at org.apache.pulsar.client.impl.ConsumerImpl.hasMessageAvailableAsync(ConsumerImpl.java:2757)
     at org.apache.pulsar.client.impl.ConsumerImpl.hasMessageAvailable(ConsumerImpl.java:2694)

Reproducing the issue

 PulsarClient client = PulsarClient.builder().serviceUrl("pulsar://localhost:6650").build();
 
 Consumer<byte[]> consumer = client.newConsumer()
     .topic("persistent://my-tenant/my-ns/my-topic")
     .subscriptionName("my-sub")
     .subscriptionType(SubscriptionType.Exclusive)
     .subscribe();
 
 // Throws UnsupportedOperationException BEFORE any readNext() call:
 boolean hasMessages = consumer.hasMessageAvailable();

Note: The exception does not occur if consumer.receive() / consumer.receive(timeout, unit) is called at least once first, because lastDequeuedMessageId is then non-earliest and hasMoreMessages takes a different code path.

Additional information

No response

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugThe PR fixed a bug or issue reported a bug

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions