{"record":{"id":"46195bcd9f177143","repo":"apache/pulsar","slug":"error-contacting-zookeeper","errorCode":null,"errorMessage":"Error contacting zookeeper","messagePattern":"Error contacting zookeeper","errorType":"exception","errorClass":"ReplicationException.UnavailableException","httpStatus":null,"severity":"error","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java","lineNumber":759,"sourceCode":"            throw new ReplicationException.UnavailableException(\n                    \"Exception while resuming auto ledger re-replication\", ee);\n        } catch (InterruptedException ie) {\n            Thread.currentThread().interrupt();\n            throw new ReplicationException.UnavailableException(\n                    \"Interrupted while resuming auto ledger re-replication\", ie);\n        }\n    }\n\n    @Override\n    public boolean isLedgerReplicationEnabled()\n            throws ReplicationException.UnavailableException {\n        log.debug(\"isLedgerReplicationEnabled()\");\n        try {\n            return !store.exists(replicationDisablePath)\n                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        } catch (ExecutionException | TimeoutException ee) {\n            log.error().exception(ee).log(\"Error while checking the state of ledger re-replication\");\n            throw new ReplicationException.UnavailableException(\n                    \"Error contacting zookeeper\", ee);\n        } catch (InterruptedException ie) {\n            Thread.currentThread().interrupt();\n            throw new ReplicationException.UnavailableException(\n                    \"Interrupted while contacting zookeeper\", ie);\n        }\n    }\n\n    @Override\n    public void notifyLedgerReplicationEnabled(final BookkeeperInternalCallbacks.GenericCallback<Void> cb)\n            throws ReplicationException.UnavailableException {\n        log.debug(\"notifyLedgerReplicationEnabled()\");\n        synchronized (replicationEnabledCallbacks) {\n            replicationEnabledCallbacks.add(cb);\n        }\n        try {\n            if (!store.exists(replicationDisablePath)\n                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS)) {","sourceCodeStart":741,"sourceCodeEnd":777,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java#L741-L777","documentation":"Thrown by isLedgerReplicationEnabled() when the blocking exists() check on the replication-disable node in the metadata store fails (ExecutionException) or times out (TimeoutException). The method answers whether auto re-replication is currently enabled by testing the absence of the node; without a working store it cannot answer, so it throws ReplicationException.UnavailableException with this legacy message.","triggerScenarios":"Calling isLedgerReplicationEnabled() while the metadata store is down, session expired, or the exists() call exceeds BLOCKING_CALL_TIMEOUT.","commonSituations":"Health/status checks during a ZooKeeper outage; monitoring scripts polling replication state while the metadata service is saturated or unreachable.","solutions":["Verify metadata store health before querying replication state.","Catch this exception and treat state as unknown rather than enabled/disabled in monitoring logic.","Check the wrapped cause for the root store error (connection loss, session expired).","Retry with backoff; exists() is read-only and safe to repeat."],"exampleFix":"// before\nboolean enabled = urManager.isLedgerReplicationEnabled(); // throws during ZK outage\n// after\nboolean enabled;\ntry {\n    enabled = urManager.isLedgerReplicationEnabled();\n} catch (ReplicationException.UnavailableException e) {\n    enabled = true; // fail open or report unknown state\n    log.warn(\"Cannot determine replication state\", e);\n}","handlingStrategy":"try-catch","validationCode":"// probe store liveness before asking replication state\nstore.exists(\"/admin/probe\").get(5, TimeUnit.SECONDS);","typeGuard":"Optional<Boolean> safeReplicationEnabled(LedgerUnderreplicationManager m) {\n    try { return Optional.of(m.isLedgerReplicationEnabled()); }\n    catch (ReplicationException.UnavailableException e) { return Optional.empty(); }\n}","tryCatchPattern":"try {\n    boolean enabled = urManager.isLedgerReplicationEnabled();\n} catch (ReplicationException.UnavailableException e) {\n    // state unknown: do not assume enabled; mark metric 'replication_state_unknown'\n}","preventionTips":["Fail monitoring checks open/explicitly rather than inferring state from exceptions.","Cache the last known replication state to ride through brief store blips.","Set alerts on metadata store latency so exists() checks do not time out."],"tags":["metadata-store","zookeeper","timeout"],"backgroundTag":"metadata-store-unavailable","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}