apache/pulsar · error · ReplicationException.UnavailableException

Failed to check if ledger is beinge replicated

Error message

Failed to check if ledger is beinge replicated

What it means

Thrown by isLedgerBeingReplicated(ledgerId) when the blocking exists() check on the per-ledger underreplication lock path (getUrLedgerLockPath(urLockPath, ledgerId)) fails for any reason. This method tells whether a given ledger is currently being re-replicated by a bookie; any store error or timeout is wrapped into ReplicationException.UnavailableException. Note the message contains a typo ('beinge') kept for API compatibility.

Source

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

            log.error().exception(ee).log("Error while checking the state of ledger re-replication");
            throw new ReplicationException.UnavailableException(
                    "Error contacting zookeeper", ee);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
            throw new ReplicationException.UnavailableException(
                    "Interrupted while contacting zookeeper", ie);
        }
    }

    /**
     * Check whether the ledger is being replicated by any bookie.
     */
    @Override
    public boolean isLedgerBeingReplicated(long ledgerId) throws ReplicationException {
        try {
            return store.exists(getUrLedgerLockPath(urLockPath, ledgerId)).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
        } catch (Exception e) {
            throw new ReplicationException.UnavailableException("Failed to check if ledger is beinge replicated", e);
        }
    }

    @Override
    public boolean initializeLostBookieRecoveryDelay(int lostBookieRecoveryDelay) throws
            ReplicationException.UnavailableException {
        log.debug("initializeLostBookieRecoveryDelay()");
        try {
            store.put(lostBookieRecoveryDelayPath, Integer.toString(lostBookieRecoveryDelay).getBytes(UTF_8),
                    Optional.of(-1L)).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
        } catch (ExecutionException ee) {
            if (ee.getCause() instanceof MetadataStoreException.BadVersionException) {
                log.info("lostBookieRecoveryDelay node is already present, so using existing value");
                return false;
            } else {
                log.error().exception(ee).log("Error while initializing LostBookieRecoveryDelay");
                throw new ReplicationException.UnavailableException("Error contacting zookeeper", ee);
            }

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify metadata store health and connectivity first.
  2. Inspect the wrapped cause (getCause()) to distinguish store outage from bad ledger-id/path issues.
  3. Retry with backoff; the check is read-only.
  4. Reduce per-ledger polling frequency if timeouts come from load.

Example fix

// before
boolean replicating = urManager.isLedgerBeingReplicated(ledgerId);
// after
boolean replicating;
try {
    replicating = urManager.isLedgerBeingReplicated(ledgerId);
} catch (ReplicationException.UnavailableException e) {
    log.warn("Cannot check replication state for ledger {}, treating as not replicating", ledgerId, e);
    replicating = false;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate store liveness and sane ledgerId before the per-ledger check
if (ledgerId < 0) throw new IllegalArgumentException("bad ledgerId");
store.exists("/probe").get(5, TimeUnit.SECONDS);

Type guard

Optional<Boolean> safeIsBeingReplicated(LedgerUnderreplicationManager m, long ledgerId) {
    try { return Optional.of(m.isLedgerBeingReplicated(ledgerId)); }
    catch (ReplicationException.UnavailableException e) { return Optional.empty(); }
}

Try / catch

try {
    replicating = urManager.isLedgerBeingReplicated(ledgerId);
} catch (ReplicationException.UnavailableException e) {
    // conservative default: assume not replicating, log cause for triage
    replicating = false;
}

Prevention

When it happens

Trigger: Calling isLedgerBeingReplicated(ledgerId) while the metadata store is down, the lock-path lookup fails (e.g. metadata service error), or the call exceeds BLOCKING_CALL_TIMEOUT. Unlike sibling methods, this catches all Exceptions including RuntimeException.

Common situations: Recovery tooling checking replication progress during a ZooKeeper outage; ledger id formatting producing a valid path but the store being unreachable; monitoring dashboards hitting this per-ledger check at scale and timing out.

Related errors


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