{"record":{"id":"fea1e3cb3a90d789","repo":"apache/pulsar","slug":"error-while-getting-replicationworkerid-rereplicat","errorCode":null,"errorMessage":"Error while getting ReplicationWorkerId rereplicating Ledger","messagePattern":"Error while getting ReplicationWorkerId rereplicating Ledger","errorType":"exception","errorClass":"ReplicationException.UnavailableException","httpStatus":null,"severity":"error","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java","lineNumber":904,"sourceCode":"    @Override\n    public String getReplicationWorkerIdRereplicatingLedger(long ledgerId)\n            throws ReplicationException.UnavailableException {\n\n        try {\n            Optional<GetResult> optRes = store.get(getUrLedgerLockPath(urLockPath, ledgerId))\n                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n            if (!optRes.isPresent()) {\n                // this is ok.\n                return null;\n            }\n\n            byte[] lockData = optRes.get().getValue();\n            LockDataFormat lock = new LockDataFormat();\n            lock.parseFromTextFormat(lockData);\n            return lock.getBookieId();\n        } catch (ExecutionException | TimeoutException e) {\n            log.error().exception(e).log(\"Error while getting ReplicationWorkerId rereplicating Ledger\");\n            throw new ReplicationException.UnavailableException(\n                    \"Error while getting ReplicationWorkerId rereplicating Ledger\", e);\n        } catch (InterruptedException e) {\n            log.error().exception(e).log(\"Got interrupted while getting ReplicationWorkerId rereplicating Ledger\");\n            Thread.currentThread().interrupt();\n            throw new ReplicationException.UnavailableException(\"Interrupted while contacting zookeeper\", e);\n        } catch (RuntimeException e) {\n            log.error().exception(e).log(\"Error while parsing ZK data of lock\");\n            throw new ReplicationException.UnavailableException(\"Error while parsing ZK data of lock\", e);\n        }\n    }\n\n    @Override\n    public void setCheckAllLedgersCTime(long checkAllLedgersCTime) throws ReplicationException.UnavailableException {\n        log.debug(\"setCheckAllLedgersCTime\");\n        try {\n            CheckAllLedgersFormat builder = new CheckAllLedgersFormat();\n            builder.setCheckAllLedgersCTime(checkAllLedgersCTime);\n            byte[] checkAllLedgersFormatByteArray = builder.toByteArray();","sourceCodeStart":886,"sourceCodeEnd":922,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java#L886-L922","documentation":"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.","triggerScenarios":"Calling getReplicationWorkerIdRereplicatingLedger(ledgerId) when store.get(getUrLedgerLockPath(urLockPath, ledgerId)) completes exceptionally (connection loss, session expiry) or exceeds BLOCKING_CALL_TIMEOUT.","commonSituations":"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.","solutions":["Verify ZooKeeper health and connectivity from the querying host","Retry the lookup; transient ConnectionLoss during bookie-failure storms usually clears once the quorum stabilizes","Confirm the urLockPath configuration matches between the brokers that write and the tools that read the lock path","Inspect the wrapped cause for KeeperException type to distinguish network from state problems"],"exampleFix":"// before\nString bookie = urManager.getReplicationWorkerIdRereplicatingLedger(ledgerId); // throws on ZK hiccup\n\n// after\nString bookie;\ntry {\n    bookie = urManager.getReplicationWorkerIdRereplicatingLedger(ledgerId);\n} catch (ReplicationException.UnavailableException e) {\n    bookie = null; // unknown owner; retry later\n}","handlingStrategy":"retry","validationCode":"// confirm metadata store reachable before ownership lookups\ntry {\n    urManager.getLostBookieRecoveryDelay(); // cheap canary read\n} catch (ReplicationException.UnavailableException e) {\n    return; // skip lock lookups this cycle\n}","typeGuard":null,"tryCatchPattern":"try {\n    String owner = urManager.getReplicationWorkerIdRereplicatingLedger(ledgerId);\n} catch (ReplicationException.UnavailableException e) {\n    if (Thread.currentThread().isInterrupted()) return;\n    owner = retryOrUnknownOwner(ledgerId);\n}","preventionTips":["Use null return (node absent) as the 'not locked' signal, not an exception path","Throttle bulk ownership queries during bookie-failure storms to protect ZK","Align urLockPath configuration across brokers and admin tooling","Retry transient lookups with backoff instead of failing the replication check"],"tags":["zookeeper","metadata-store","ledger-lock","bookkeeper"],"backgroundTag":"zookeeper-unavailable","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}