apache/pulsar · error · org.apache.pulsar.client.impl.v5.PulsarClientException

${cause}

Error message

${cause}

What it means

ProducerBuilderV5.create() blocks on createAsync() and unwraps the CompletionException. Any failure from the async producer-creation pipeline (DAG watch session start, topic layout fetch, segment attach) that is not already a v5 PulsarClientException is rethrown as a plain v5 PulsarClientException wrapping the original cause. It is the library's way of keeping the checked-exception surface uniform across the sync create() path.

Source

Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/ProducerBuilderV5.java:65

    ProducerBuilderV5(PulsarClientV5 client, Schema<T> v5Schema) {
        this.client = client;
        this.v5Schema = v5Schema;
    }

    @Override
    public Producer<T> create() throws PulsarClientException {
        try {
            return createAsync().join();
        } catch (java.util.concurrent.CompletionException e) {
            Throwable cause = e.getCause();
            if (cause instanceof PulsarClientException pce) {
                throw pce;
            }
            if (cause instanceof org.apache.pulsar.client.api.PulsarClientException.NotFoundException) {
                throw new PulsarClientException.NotFoundException(cause.getMessage());
            }
            throw new PulsarClientException(cause);
        }
    }

    @Override
    public CompletableFuture<Producer<T>> createAsync() {
        String topicStr = conf.getTopicName();
        if (topicStr == null || topicStr.isEmpty()) {
            return CompletableFuture.failedFuture(
                    new PulsarClientException.InvalidConfigurationException("Topic name is required"));
        }

        TopicName topicName = V5Utils.parseScalableTopicInput(topicStr);

        // Create DAG watch client and start the session
        DagWatchClient dagWatch = new DagWatchClient(client.v4Client(), topicName);

        return dagWatch.start()
                .thenCompose(initialLayout -> {

View on GitHub (pinned to 820761864e)

Solutions

  1. Read the wrapped cause via e.getCause() (or print the full stack trace) to see the real failure; fix that root problem.
  2. If the cause is 'topic not found', create the topic or enable auto-creation on the broker.
  3. Verify broker connectivity (serviceUrl, TLS config) before create(); the v5 client connects lazily during producer creation.
  4. For transient network errors, retry create() with backoff; for configuration errors, fix the builder settings instead.

Example fix

// before
Producer<T> p = client.newProducer(schema).topic(topic).create(); // opaque PulsarClientException
// after
try {
    Producer<T> p = client.newProducer(schema).topic(topic).create();
} catch (PulsarClientException e) {
    LOG.error("producer create failed", e.getCause() != null ? e.getCause() : e);
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (topic == null || topic.isEmpty()) throw new IllegalArgumentException("topic required before create()");

Try / catch

try {
    Producer<T> p = builder.create();
} catch (PulsarClientException e) {
    Throwable root = e.getCause() != null ? e.getCause() : e;
    if (root instanceof java.util.concurrent.CompletionException ce) root = ce.getCause();
    LOG.error("producer creation failed: {}", root.toString(), root);
    throw e;
}

Prevention

When it happens

Trigger: Calling producerBuilder.create() when the async pipeline fails with a non-PulsarClientException: e.g. the broker rejects the topic (v4 NotFoundException is mapped specially), a connection drops mid-attach, a timeout in DagWatchClient.start(), or any RuntimeException bubbling out of eagerAttachInitialAsync().

Common situations: Topic does not exist and auto-creation is disabled; broker unreachable or TLS handshake failure during segment attach; schema/serialization setup errors; a v4 client that was closed while a producer was being created.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/0fa08506aa6c6ac8. Report an issue: GitHub.