openzipkin/zipkin · critical · RuntimeException

Pulsar client creation failed. {}

Error message

Pulsar client creation failed. {}

What it means

LazyPulsarInit.subscribe() wraps any exception thrown while building the PulsarClient in a RuntimeException ('Pulsar client creation failed. ...'). PulsarClient.builder().loadConf(clientProps).build() fails on an invalid/unreachable serviceUrl, missing required config, bad auth settings, or incompatible client/broker versions. The CheckResult is also recorded as failed so the collector's check() reports unhealthy.

Source

Thrown at zipkin-collector/pulsar/src/main/java/zipkin2/collector/pulsar/LazyPulsarInit.java:53

  void init() {
    if (result == null) {
      synchronized (this) {
        if (result == null) {
          result = subscribe();
        }
      }
    }
  }

  private PulsarClient subscribe() {
    PulsarClient client;
    try {
      client = PulsarClient.builder()
          .loadConf(clientProps)
          .build();
    } catch (Exception e) {
      failure.set(CheckResult.failed(e));
      throw new RuntimeException("Pulsar client creation failed. " + e.getMessage(), e);
    }

    try {
      for (int i = 0; i < concurrency; i++) {
        PulsarSpanConsumer consumer = new PulsarSpanConsumer(topic, consumerProps, client, collector, metrics);
        consumer.startConsumer();
      }
      return client;
    } catch (Exception e) {
      try {
        client.close();
      } catch (PulsarClientException ex) {
        // Nobody cares me.
      }
      failure.set(CheckResult.failed(e));
      throw new RuntimeException("Pulsar Client is unable to subscribe to the topic(" + topic + "), please check the service.", e);
    }
  }

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Verify the serviceUrl format, e.g. pulsar://my-broker:6650, and that the broker host:port is reachable (telnet/grpcurl)
  2. Check the wrapped cause (e) in the stack trace — it names the real PulsarClientException reason
  3. Validate TLS/authentication settings in clientProps against the broker configuration
  4. Check client/broker version compatibility if the cause indicates an unsupported protocol

Example fix

// before
PulsarCollector.newBuilder(ctx)
  .serviceUrl("my-broker:6650") // missing scheme
  ...

// after
PulsarCollector.newBuilder(ctx)
  .serviceUrl("pulsar://my-broker:6650")
  ...
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the URL shape before building the collector
URI uri = URI.create(serviceUrl);
if (!("pulsar".equals(uri.getScheme()) || "http".equals(uri.getScheme()) || "https".equals(uri.getScheme()))) {
  throw new IllegalArgumentException("serviceUrl must start with pulsar:// or http(s)://");
}

Try / catch

try {
  collector.check(); // triggers lazy init
} catch (RuntimeException e) {
  Throwable cause = e.getCause();
  log.error("Pulsar client init failed: {}", cause.getMessage(), e);
  // surface as unhealthy and let orchestration restart/backoff
}

Prevention

When it happens

Trigger: PulsarCollector built with a malformed serviceUrl (not pulsar://host:port or http://...), a broker that is unreachable at connect time, invalid TLS/auth configuration in clientProps, or a Pulsar client version mismatch. The error surfaces lazily on first use (check()/accept of the first span), not at build().

Common situations: Service URL typo (e.g. missing pulsar:// scheme), broker DNS not resolvable in Kubernetes, TLS enabled broker with plaintext client config, or auth plugin not on the classpath.

Related errors


AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14). Data as JSON: /api/errors/eac39947261ec723. Report an issue: GitHub.