apache/pulsar · warning · RuntimeException

RuntimeException

Error message

RuntimeException

What it means

tryToBecomeAuditor() blocks in wait() until leadership is acquired or the session expires. If the waiting thread is interrupted, the InterruptedException is wrapped in a RuntimeException and rethrown, since the method signature has no checked exceptions. This indicates the thread was interrupted (e.g., during broker shutdown) while waiting to become auditor.

Source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerAuditorManager.java:94

        synchronized (this) {
            leaderElectionState = les;
        }

        while (true) {
            try {
                synchronized (this) {
                    if (sessionExpired) {
                        throw new IllegalStateException("Zookeeper session expired, give up to become auditor.");
                    }
                    if (leaderElectionState == LeaderElectionState.Leading) {
                        return;
                    } else {
                        wait();
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public BookieId getCurrentAuditor() {
        return leaderElection.getLeaderValue()
                .join()
                .map(BookieId::parse)
                .orElse(null);
    }

    @Override
    public void close() throws Exception {
        leaderElection.close();
        coordinationService.close();
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. This is expected during shutdown — treat it as benign and stop the election attempt rather than retrying on the same thread.
  2. If it occurs outside shutdown, audit who interrupts the thread and fix the lifecycle management of the auditor-election thread.
  3. On receiving it, check Thread.currentThread().isInterrupted() / reassert interrupt status in surrounding lifecycle code.
  4. Run the election on a dedicated daemon thread with a well-defined shutdown path instead of an ad-hoc thread.

Example fix

// before
coordinator.tryToBecomeAuditor();
// after
try {
    coordinator.tryToBecomeAuditor();
} catch (RuntimeException e) {
    if (e.getCause() instanceof InterruptedException) {
        Thread.currentThread().interrupt();
        LOG.info("Auditor election interrupted, stopping");
    } else {
        throw e;
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Run election on a dedicated thread and check interrupt state first
if (Thread.currentThread().isInterrupted()) {
    return; // do not start election on an interrupted thread
}

Try / catch

try {
    coordinator.tryToBecomeAuditor();
} catch (RuntimeException e) {
    if (e.getCause() instanceof InterruptedException) {
        Thread.currentThread().interrupt(); // restore status and stop election
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling tryToBecomeAuditor() on a thread that gets interrupted (Thread.interrupt()) while parked in wait() inside the leadership loop — typically during broker shutdown, executor termination, or manual thread cancellation.

Common situations: Broker graceful shutdown interrupting the audit-election thread; unit tests cancelling futures/threads; thread pool shutdownNow() during redeployment.

Related errors


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