apache/pulsar · error · IllegalStateException

Interrupted initializing OAuth2 IdP TLS factory

Error message

Interrupted initializing OAuth2 IdP TLS factory

What it means

During OAuth2 client setup, StandaloneOAuth2HttpClientFactory asynchronously initializes a TLS factory for the identity-provider connection. If the thread waiting on `factory.initialize(...).get()` is interrupted, the factory is closed, the interrupt flag is restored, and this IllegalStateException is thrown. It means initialization was cancelled, typically by application or client shutdown.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/StandaloneOAuth2HttpClientFactory.java:113

            if (executor != null) {
                executor.shutdownNow();
            }
            throw e;
        }
    }

    private static PulsarTlsFactory buildIdpTlsFactory(TlsPolicy policy, int refreshIntervalSeconds,
            ScheduledExecutorService executor) {
        FileBasedTlsFactory factory = new FileBasedTlsFactory(
                Map.of(TlsPurpose.CLIENT_OAUTH2, policy),
                FileBasedTlsFactorySettings.builder().refreshIntervalSeconds(refreshIntervalSeconds).build(),
                Map.of());
        try {
            factory.initialize(initContext(executor)).get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            closeQuietly(factory);
            throw new IllegalStateException("Interrupted initializing OAuth2 IdP TLS factory", e);
        } catch (ExecutionException e) {
            closeQuietly(factory);
            Throwable cause = e.getCause() != null ? e.getCause() : e;
            throw new IllegalStateException("Failed to initialize OAuth2 IdP TLS factory: " + cause.getMessage(),
                    cause);
        }
        return factory;
    }

    private static TlsFactoryInitContext initContext(ScheduledExecutorService executor) {
        return new TlsFactoryInitContext() {
            @Override
            public Map<String, String> params() {
                return Map.of();
            }

            @Override
            public ScheduledExecutorService scheduler() {

View on GitHub (pinned to 820761864e)

Solutions

  1. Retry client creation from a non-interrupted thread after shutdown activity settles.
  2. Fix lifecycle ordering: never construct the OAuth2 client concurrently with closing the Pulsar client or its executors.
  3. Find the interrupt source (Future.cancel(true), shutdownNow) and sequence OAuth2 init before shutdown.
  4. Preserve the interrupt status in caller code; do not swallow InterruptedException upstream.
Defensive patterns

Strategy: retry

Validate before calling

if (Thread.currentThread().isInterrupted()) {
    throw new IllegalStateException("Cannot init OAuth2 client on an interrupted thread");
}

Try / catch

try {
    client = AuthenticationFactoryOAuth2.clientCredentials(issuerUrl, credFile, audience);
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("Interrupted initializing")) {
        // thread was interrupted during TLS factory init;
        // propagate shutdown or retry on a fresh thread after checks
        throw e;
    }
    throw e;
}

Prevention

When it happens

Trigger: AuthenticationFactoryOAuth2.clientCredentials/refreshToken invoked from a thread interrupted while blocked on the TLS-factory initialization future — e.g. during Pulsar client close, executor shutdownNow, or Future.cancel(true) racing client construction.

Common situations: Container/pod shutdown racing client creation; framework timeouts interrupting worker threads; reusing a shutting-down ScheduledExecutorService; lifecycle misordering where init races close.

Understand the failure class

Related errors


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