apache/pulsar · error · RuntimeException

Bookie failed to start within timeout period

Error message

Bookie failed to start within timeout period

What it means

RuntimeException thrown by BKCluster.startBookie in the test harness when a newly started Bookie server does not reach Lifecycle.State.STARTED within the polling timeout. It indicates the bookie process failed or stalled during startup rather than a client API misuse.

Source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/BKCluster.java:320

                org.apache.bookkeeper.server.Main.buildBookieServer(new BookieConfiguration(conf));

        BookieId address = BookieImpl.getBookieId(conf);
        // Start the bookie directly instead of using ComponentStarter.startComponent()
        // which registers JVM shutdown hooks that are never cleaned up and can cause
        // System.exit() during test cleanup, killing the test JVM.
        server.start();

        // Wait for up to 30 seconds for the bookie to start
        for (int i = 0; i < 3000; i++) {
            if (server.lifecycleState() == Lifecycle.State.STARTED) {
                break;
            }

            Thread.sleep(10);
        }

        if (server.lifecycleState() != Lifecycle.State.STARTED) {
            throw new RuntimeException("Bookie failed to start within timeout period");
        }

        log.info().attr("address", address).log("New bookie has been created");

        return server;
    }

    private void startAutoRecovery(BookieServer bserver,
                                   ServerConfiguration conf) throws Exception {
        if (isAutoRecoveryEnabled()) {
            AutoRecoveryMain autoRecoveryProcess = new AutoRecoveryMain(conf);
            autoRecoveryProcess.start();
            autoRecoveryProcesses.put(bserver, autoRecoveryProcess);
            log.debug().attr("bookieId", bserver.getBookieId()).log("Starting Auditor Recovery for the bookie");
        }
    }

    private ServerConfiguration newBaseServerConfiguration() {

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the bookie server logs for the underlying startup exception (port bind failure, disk errors, metadata connection failures)
  2. Verify the metadata store is running and reachable before starting bookies
  3. Check that bookie journal/ledger directories exist and are writable
  4. Increase the startup wait window or ensure port ranges are free in the test environment

Example fix

// before
server = bkCluster.startBookie(...); // RuntimeException after timeout
// after
// free the port / fix dirs first, then:
await().atMost(Duration.ofSeconds(30)).until(() -> portIsFree(bookiePort));
BookieServer server = bkCluster.startBookie(...);
Defensive patterns

Strategy: retry

Validate before calling

await().atMost(Duration.ofSeconds(30)).until(() -> portIsFree(bookiePort));
// also verify metadata store is up before starting bookies

Try / catch

try {
    BookieServer s = bkCluster.startBookie(...);
} catch (RuntimeException e) {
    if (e.getMessage().contains("failed to start within timeout")) {
        // dump bookie logs, fix env, then restart
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling startBookie (via startAllBookies or server) when the bookie throws during startup — bad bookie configuration, port conflicts, disk/journal directories unwritable, or metadata store unreachable — so the polling loop exhausts its timeout while lifecycleState() != STARTED.

Common situations: Port already in use in CI; journal/index directories not writable; metadata service not started before the bookie; bookie startup crash hidden in bookie logs.

Understand the failure class

Related errors


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