apache/pulsar · error · RuntimeException

Failed to initialize controller for ${topic}

Error message

Failed to initialize controller for ${topic}

What it means

ScalableTopicService.getOrCreateController asynchronously creates and initializes a per-topic controller. If controller.initialize() fails, the stored future is evicted from the cache so callers can retry, and the failure is rethrown wrapped in a RuntimeException naming the topic, preserving the original cause.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/scalable/ScalableTopicService.java:111

    // --- Controller management ---

    /**
     * Get or create a controller for a scalable topic. The controller will attempt
     * leader election; only the leader actively coordinates consumers.
     */
    public CompletableFuture<ScalableTopicController> getOrCreateController(TopicName topic) {
        String key = topic.toString();
        CompletableFuture<ScalableTopicController> stored = controllers.computeIfAbsent(key, k -> {
            ScalableTopicController controller = new ScalableTopicController(
                    topic, resources, brokerService, coordinationService);
            return controller.initialize().thenApply(__ -> controller);
        });
        // Evict failed futures so subsequent callers can retry. This runs *outside*
        // computeIfAbsent, so modifying the map here is safe.
        return stored.exceptionally(ex -> {
            controllers.remove(key, stored);
            throw new RuntimeException("Failed to initialize controller for " + topic, ex);
        });
    }

    /**
     * Release the controller for a topic (e.g., on topic unload).
     */
    public CompletableFuture<Void> releaseController(TopicName topic) {
        CompletableFuture<ScalableTopicController> future = controllers.remove(topic.toString());
        if (future != null) {
            return future.thenCompose(ScalableTopicController::close);
        }
        return CompletableFuture.completedFuture(null);
    }

    // --- Admin operations ---

    /**
     * Create a new scalable topic with the given number of initial segments.

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the cause chain (getCause()) for the real initialization failure
  2. Retry the operation — the failed future is evicted so a fresh controller is built
  3. Check topic metadata/storage health for the named topic; unload the topic to reset state

Example fix

// handling
try {
    controller = service.getOrCreateController(topic).join();
} catch (CompletionException e) {
    log.warn("controller init failed for {}", topic, e.getCause()); // retry later
}
Defensive patterns

Strategy: retry

Validate before calling

if (!topicExists(topic)) { throw new IllegalStateException("Topic " + topic + " must exist before controller use"); }

Try / catch

try {
    controller = service.getOrCreateController(topic).join();
} catch (CompletionException e) {
    Throwable cause = e.getCause();
    log.warn("Controller init failed for {}, will retry", topic, cause); // failure was evicted, retry is safe
}

Prevention

When it happens

Trigger: Any of the callers (splitSegment, rebucketSegment, mergeSegments, create/deleteSubscription, seekSubscription) triggers getOrCreateController for a topic whose controller initialization throws (metadata load failure, storage error, etc.).

Common situations: Topic metadata corrupted or unavailable in the underlying store; broker under contention; a prior initialization left transient state that the retry now succeeds on (hence the eviction-for-retry design).

Related errors


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