apache/pulsar · error · ReplicationException.UnavailableException

Error while getting ReplicationWorkerId rereplicating Ledger

Error message

Error while getting ReplicationWorkerId rereplicating Ledger

What it means

getReplicationWorkerIdRereplicatingLedger(long) reads the underreplication lock znode for a ledger and parses its LockDataFormat (text/JSON protobuf) to find the bookie (ReplicationWorker id) that is re-replicating it. If the metadata store get future fails or times out, it throws ReplicationException.UnavailableException('Error while getting ReplicationWorkerId rereplicating Ledger'), meaning the lock state could not be read; a missing node is normal and returns null.

Source

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

    @Override
    public String getReplicationWorkerIdRereplicatingLedger(long ledgerId)
            throws ReplicationException.UnavailableException {

        try {
            Optional<GetResult> optRes = store.get(getUrLedgerLockPath(urLockPath, ledgerId))
                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
            if (!optRes.isPresent()) {
                // this is ok.
                return null;
            }

            byte[] lockData = optRes.get().getValue();
            LockDataFormat lock = new LockDataFormat();
            lock.parseFromTextFormat(lockData);
            return lock.getBookieId();
        } catch (ExecutionException | TimeoutException e) {
            log.error().exception(e).log("Error while getting ReplicationWorkerId rereplicating Ledger");
            throw new ReplicationException.UnavailableException(
                    "Error while getting ReplicationWorkerId rereplicating Ledger", e);
        } catch (InterruptedException e) {
            log.error().exception(e).log("Got interrupted while getting ReplicationWorkerId rereplicating Ledger");
            Thread.currentThread().interrupt();
            throw new ReplicationException.UnavailableException("Interrupted while contacting zookeeper", e);
        } catch (RuntimeException e) {
            log.error().exception(e).log("Error while parsing ZK data of lock");
            throw new ReplicationException.UnavailableException("Error while parsing ZK data of lock", e);
        }
    }

    @Override
    public void setCheckAllLedgersCTime(long checkAllLedgersCTime) throws ReplicationException.UnavailableException {
        log.debug("setCheckAllLedgersCTime");
        try {
            CheckAllLedgersFormat builder = new CheckAllLedgersFormat();
            builder.setCheckAllLedgersCTime(checkAllLedgersCTime);
            byte[] checkAllLedgersFormatByteArray = builder.toByteArray();

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify ZooKeeper health and connectivity from the querying host
  2. Retry the lookup; transient ConnectionLoss during bookie-failure storms usually clears once the quorum stabilizes
  3. Confirm the urLockPath configuration matches between the brokers that write and the tools that read the lock path
  4. Inspect the wrapped cause for KeeperException type to distinguish network from state problems

Example fix

// before
String bookie = urManager.getReplicationWorkerIdRereplicatingLedger(ledgerId); // throws on ZK hiccup

// after
String bookie;
try {
    bookie = urManager.getReplicationWorkerIdRereplicatingLedger(ledgerId);
} catch (ReplicationException.UnavailableException e) {
    bookie = null; // unknown owner; retry later
}
Defensive patterns

Strategy: retry

Validate before calling

// confirm metadata store reachable before ownership lookups
try {
    urManager.getLostBookieRecoveryDelay(); // cheap canary read
} catch (ReplicationException.UnavailableException e) {
    return; // skip lock lookups this cycle
}

Try / catch

try {
    String owner = urManager.getReplicationWorkerIdRereplicatingLedger(ledgerId);
} catch (ReplicationException.UnavailableException e) {
    if (Thread.currentThread().isInterrupted()) return;
    owner = retryOrUnknownOwner(ledgerId);
}

Prevention

When it happens

Trigger: Calling getReplicationWorkerIdRereplicatingLedger(ledgerId) when store.get(getUrLedgerLockPath(urLockPath, ledgerId)) completes exceptionally (connection loss, session expiry) or exceeds BLOCKING_CALL_TIMEOUT.

Common situations: Admin tooling / ReplicationCheck querying which worker holds a ledger lock during a ZK degradation; many rapid queries during a bookie failure storm overloading ZK; network partition between broker and ZK.

Related errors


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