apache/pulsar · warning · ReplicationException.UnavailableException

Interrupted while stopping auto ledger re-replication

Error message

Interrupted while stopping auto ledger re-replication

What it means

Thrown by disableLedgerReplication() when the thread blocked on the replication-disable marker put is interrupted. The interrupt flag is restored and the InterruptedException is wrapped as ReplicationException.UnavailableException. The disable marker may or may not have been written — re-check replication state afterwards.

Source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java:726

            throw new ReplicationException.UnavailableException("Interrupted while connecting metadata store", ie);
        }
    }

    @Override
    public void disableLedgerReplication()
            throws ReplicationException.UnavailableException {
        log.debug("disableLedgerReplication()");
        try {
            store.put(replicationDisablePath, "".getBytes(UTF_8), Optional.of(-1L))
                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
            log.info("Auto ledger re-replication is disabled!");
        } catch (ExecutionException | TimeoutException ee) {
            log.error().exception(ee).log("Exception while stopping auto ledger re-replication");
            throw new ReplicationException.UnavailableException(
                    "Exception while stopping auto ledger re-replication", ee);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
            throw new ReplicationException.UnavailableException(
                    "Interrupted while stopping auto ledger re-replication", ie);
        }
    }

    @Override
    public void enableLedgerReplication()
            throws ReplicationException.UnavailableException {
        log.debug("enableLedgerReplication()");
        try {
            store.delete(replicationDisablePath, Optional.empty())
                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
            log.info("Resuming automatic ledger re-replication");
        } catch (ExecutionException | TimeoutException ee) {
            log.error().exception(ee).log("Exception while resuming ledger replication");
            throw new ReplicationException.UnavailableException(
                    "Exception while resuming auto ledger re-replication", ee);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();

View on GitHub (pinned to 820761864e)

Solutions

  1. After the interrupt, verify whether auto re-replication is actually disabled (isLedgerReplicationEnabled / check the disable node) before re-issuing.
  2. Re-run disableLedgerReplication() if the marker was not persisted and disabling is still required.
  3. Avoid interrupting admin operations that mutate metadata state; use cooperative cancellation.
  4. Preserve interrupt status and surface the state ambiguity to the operator instead of silently retrying.

Example fix

// before
manager.disableLedgerReplication();
// after
try {
    manager.disableLedgerReplication();
} catch (ReplicationException.UnavailableException e) {
    if (!manager.isLedgerReplicationEnabled()) {
        return; // marker was written despite the interrupt
    }
    retryWithBackoff(() -> manager.disableLedgerReplication());
}
Defensive patterns

Strategy: try-catch

Type guard

static boolean interruptedDuringDisable(ReplicationException.UnavailableException e) {
    return e.getCause() instanceof InterruptedException;
}

Try / catch

try {
    manager.disableLedgerReplication();
} catch (ReplicationException.UnavailableException e) {
    if (interruptedDuringDisable(e)) {
        Thread.currentThread().interrupt();
        // re-check state: if (!manager.isLedgerReplicationEnabled()) marker landed
        return;
    }
    throw e;
}

Prevention

When it happens

Trigger: Interrupting the caller of disableLedgerReplication() while store.put(replicationDisablePath,...).get(...) is blocked, e.g. during admin-task cancellation or service shutdown.

Common situations: Admin CLI killed with SIGINT mid-command, admin HTTP request aborted by client disconnect handling that interrupts worker threads, or scheduled maintenance jobs cancelled at shutdown.

Related errors


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