{"record":{"id":"b87846bb911840d2","repo":"apache/pulsar","slug":"timeout-during-managed-ledger-close","errorCode":null,"errorMessage":"Timeout during managed ledger close","messagePattern":"Timeout during managed ledger close","errorType":"exception","errorClass":"ManagedLedgerException","httpStatus":null,"severity":"error","filePath":"managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerImpl.java","lineNumber":1640,"sourceCode":"        }\n        final Result result = new Result();\n\n        asyncClose(new CloseCallback() {\n            @Override\n            public void closeComplete(Object ctx) {\n                counter.countDown();\n            }\n\n            @Override\n            public void closeFailed(ManagedLedgerException exception, Object ctx) {\n                result.exception = exception;\n                counter.countDown();\n            }\n\n        }, null);\n\n        if (!counter.await(AsyncOperationTimeoutSeconds, TimeUnit.SECONDS)) {\n            throw new ManagedLedgerException(\"Timeout during managed ledger close\");\n        }\n\n        if (result.exception != null) {\n            log.error().exception(result.exception).log(\"Error closing managed ledger\");\n            throw result.exception;\n        }\n    }\n\n    @Override\n    public synchronized void asyncClose(final CloseCallback callback, final Object ctx) {\n        State state = STATE_UPDATER.get(this);\n        if (state.isFenced()) {\n            cancelScheduledTasks();\n            factory.close(this);\n            callback.closeFailed(new ManagedLedgerFencedException(), ctx);\n            return;\n        } else if (state == State.Closed) {\n            log.debug(\"Ignoring request to close a closed managed ledger\");","sourceCodeStart":1622,"sourceCodeEnd":1658,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerImpl.java#L1622-L1658","documentation":"ManagedLedgerImpl.close() asynchronously waits (via CountDownLatch) for all cursors and the ledger to close. If the async close does not finish within AsyncOperationTimeoutSeconds, this ManagedLedgerException is thrown. It indicates a close operation hung, usually because an async ledger/cursor close callback never completed (e.g. BookKeeper client stalled or a cursor close callback was never invoked).","triggerScenarios":"Calling the synchronous ManagedLedger close() while an async ledger close or cursor close callback is delayed beyond AsyncOperationTimeoutSeconds (default 60s) — e.g. BookKeeper client disconnected, ZooKeeper/metadata store unresponsive, or a slow in-flight write preventing the ledger from being closed.","commonSituations":"Broker shutdown/restart while the metadata store or BookKeeper cluster is degraded; network partitions to bookies; ledger recovery stuck during broker failover; tests closing ledgers with a dead mock BK client.","solutions":["Check BookKeeper and metadata-store (ZooKeeper) health; the close callback usually stalls because the underlying client is stuck","Retry the close after connectivity is restored; the ledger remains closeable unless fenced","If it recurs during shutdown, increase AsyncOperationTimeoutSeconds via the ServiceConfiguration to give slow closes more time","Inspect broker logs just before the timeout for the first async operation error — the timeout masks the root cause"],"exampleFix":"// before\nmanagedLedger.close(); // throws if BK is slow\n// after\ntry {\n    managedLedger.close();\n} catch (ManagedLedgerException e) {\n    log.warn(\"ML close timed out, scheduling retry\", e);\n    // retry close after reconnecting BookKeeper/metadata store\n}","handlingStrategy":"try-catch","validationCode":"// health check before close\nif (!bkClientConnected || !zkSessionAlive) { scheduleRetryClose(); return; }","typeGuard":null,"tryCatchPattern":"try {\n    managedLedger.close();\n} catch (ManagedLedgerException e) {\n    log.warn(\"ML close timeout; check BookKeeper/metadata-store, then retry\", e);\n}","preventionTips":["Monitor BookKeeper and ZooKeeper health before planned shutdowns","Use async close APIs in restart flows","Keep AsyncOperationTimeoutSeconds tuned to your cluster latency","Alert on close-timeout logs since they mask a root-cause failure"],"tags":["timeout","managed-ledger","bookkeeper","shutdown"],"backgroundTag":"async-operation-timeout","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"}