apache/pulsar · warning · ReplicationException.UnavailableException
Interrupted while connecting metadata store
Error message
Interrupted while connecting metadata store
What it means
Thrown by getLedgerUnreplicationInfo when the thread blocked waiting on store.get(path).get(...) is interrupted. The code re-asserts the interrupt flag (Thread.currentThread().interrupt()) before wrapping the InterruptedException in ReplicationException.UnavailableException so callers and the executor keep correct interruption semantics. It means the read of the under-replicated ledger state was cancelled rather than failed.
Source
Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java:319
}
byte[] data = optRes.get().getValue();
UnderreplicatedLedgerFormat underreplicatedLedgerFormat = new UnderreplicatedLedgerFormat();
underreplicatedLedgerFormat.parseFromTextFormat(data);
PulsarUnderreplicatedLedger underreplicatedLedger = new PulsarUnderreplicatedLedger(ledgerId);
List<String> replicaList = underreplicatedLedgerFormat.getReplicasList();
long ctime = (underreplicatedLedgerFormat.hasCtime() ? underreplicatedLedgerFormat.getCtime()
: UnderreplicatedLedger.UNASSIGNED_CTIME);
underreplicatedLedger.setCtime(ctime);
underreplicatedLedger.setReplicaList(replicaList);
return underreplicatedLedger;
} catch (ExecutionException | TimeoutException ee) {
throw new ReplicationException.UnavailableException("Error contacting with metadata store", ee);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new ReplicationException.UnavailableException("Interrupted while connecting metadata store", ie);
} catch (RuntimeException pe) {
throw new ReplicationException.UnavailableException("Error parsing proto message", pe);
}
}
@Override
public CompletableFuture<Void> markLedgerUnderreplicatedAsync(long ledgerId, Collection<String> missingReplicas) {
log.debug().attr("ledgerId", ledgerId).attr("missingReplicas", missingReplicas)
.log("markLedgerUnderreplicated");
final String path = getUrLedgerPath(ledgerId);
final CompletableFuture<Void> createFuture = new CompletableFuture<>();
tryMarkLedgerUnderreplicatedAsync(path, missingReplicas, createFuture);
return createFuture;
}
private void tryMarkLedgerUnderreplicatedAsync(final String path,
final Collection<String> missingReplicas,
final CompletableFuture<Void> finalFuture) {View on GitHub (pinned to 820761864e)
Solutions
- Treat it as expected cancellation: let the thread exit and do not swallow or clear the interrupt flag.
- If it happens unexpectedly, audit which component interrupts the Auditor thread (shutdown hooks, schedulers) and ensure reads are not started on threads about to be cancelled.
- If shutdown interrupts are too aggressive, configure orderly shutdown so in-flight replication checks complete before executor termination.
- Retry the ledger check after restart; the under-replicated state is persistent in the metadata store.
Example fix
// before
try {
UnderreplicatedLedger l = urManager.getLedgerUnreplicationInfo(ledgerId);
} catch (ReplicationException.UnavailableException e) {
log.error("failed", e); // ignores interrupt state
}
// after
try {
UnderreplicatedLedger l = urManager.getLedgerUnreplicationInfo(ledgerId);
} catch (ReplicationException.UnavailableException e) {
if (Thread.currentThread().isInterrupted()) {
return; // shutdown in progress, stop the loop
}
retryWithBackoff(...);
} Defensive patterns
Strategy: try-catch
Validate before calling
// skip the call if the thread is already interrupted
if (Thread.currentThread().isInterrupted()) {
return; // don't start blocking store reads on a cancelled thread
} Type guard
static boolean wasInterrupted(ReplicationException.UnavailableException e) {
return e.getCause() instanceof InterruptedException;
} Try / catch
try {
return urManager.getLedgerUnreplicationInfo(ledgerId);
} catch (ReplicationException.UnavailableException e) {
if (Thread.currentThread().isInterrupted()) {
return null; // shutdown path: exit promptly, don't retry
}
throw e;
} Prevention
- Ensure executors shut down tasks gracefully before shutdownNow()
- Never swallow InterruptedException without restoring the interrupt flag
- Avoid running blocking UR reads on threads subject to aggressive cancellation
- Check Thread.currentThread().isInterrupted() in long audit loops
When it happens
Trigger: Calling getLedgerUnreplicationInfo from a thread that gets interrupted while blocked on the metadata store future — e.g. broker/Auditor shutdown, executor.shutdownNow(), or another component cancelling the worker thread mid blocking get.
Common situations: Graceful shutdown of the Pulsar broker's Auditor thread; a scheduled task cancelled on timeout by an outer scheduler; test harnesses interrupting leaked blocking threads; thread pool termination during redeploy.
Related errors
- Interrupted while contacting metadata store
- Interrupted while probing the client TLS factory
- Close interrupted
- Close interrupted
- Interrupted while reading ledgers at path ${path}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/8cb5d955b94a525c.
Report an issue: GitHub.