{"record":{"id":"f0107d0fe3ddb5e1","repo":"apache/pulsar","slug":"ioexception","errorCode":null,"errorMessage":"IOException","messagePattern":"IOException","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/LongHierarchicalLedgerRangeIterator.java","lineNumber":66,"sourceCode":"    }\n\n    /**\n     * Returns all children with path as a parent.  If path is non-existent,\n     * returns an empty list anyway (after all, there are no children there).\n     * Maps all exceptions (other than NoNode) to IOException in keeping with\n     * LedgerRangeIterator.\n     *\n     * @param path\n     * @return Iterator into set of all children with path as a parent\n     * @throws IOException\n     */\n    List<String> getChildrenAt(String path) throws IOException {\n        try {\n            return store.sync(path).thenCompose(__ -> store.getChildrenFromStore(path))\n                    .get(AbstractMetadataDriver.BLOCKING_CALL_TIMEOUT, TimeUnit.MILLISECONDS);\n        } catch (ExecutionException | TimeoutException e) {\n            log.debug().attr(\"path\", path).log(\"Failed to get children\");\n            throw new IOException(e);\n        } catch (InterruptedException ie) {\n            Thread.currentThread().interrupt();\n            throw new IOException(\"Interrupted while reading ledgers at path \" + path, ie);\n        }\n    }\n\n    /**\n     * Represents the ledger range rooted at a leaf node, returns at most one LedgerRange.\n     */\n    class LeafIterator implements LedgerManager.LedgerRangeIterator {\n        // Null iff iteration is complete\n        LedgerManager.LedgerRange range;\n\n        LeafIterator(String path) throws IOException {\n            List<String> ledgerLeafNodes = getChildrenAt(path);\n            Set<Long> ledgerIds = HierarchicalLedgerUtils.ledgerListToSet(ledgerLeafNodes, ledgerRootPath, path);\n            log.debug().attr(\"hashNode\", path)\n                    .attr(\"ledgers\", ledgerIds)","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/LongHierarchicalLedgerRangeIterator.java#L48-L84","documentation":"getChildrenAt() lists the children of a metadata-store path used for hierarchical ledger enumeration. It converts async metadata-store failures (execution errors, timeouts, or thread interruption) into a plain IOException because the BookKeeper iterator API is synchronous. Thrown when the store.sync/getChildrenFromStore future fails or does not complete within BLOCKING_CALL_TIMEOUT.","triggerScenarios":"Calling LongHierarchicalLedgerRangeIterator iteration (hasMoreElements/next) that invokes getChildrenAt(path) when the metadata store is down/unreachable, the path cannot be read, or the call exceeds AbstractMetadataDriver.BLOCKING_CALL_TIMEOUT.","commonSituations":"ZooKeeper/etcd outages during ledger listing; slow or overloaded metadata store causing timeouts; interrupted threads during broker shutdown; missing/incorrect ledger metadata root path configuration.","solutions":["Check metadata store connectivity and health (ZooKeeper ensemble or service URL).","Increase BLOCKING_CALL_TIMEOUT if the store is slow, or reduce store load.","Inspect the cause via IOException#getCause for the underlying store error.","Retry iteration after the store recovers; re-create the iterator at the last successful ledger id."],"exampleFix":"// before\ntry { while (it.hasMoreElements()) { it.nextElement(); } }\ncatch (IOException e) { log.error(\"ledger range listing failed\", e); }\n// after\ntry { while (it.hasMoreElements()) { it.nextElement(); } }\ncatch (IOException e) {\n    if (e.getCause() instanceof TimeoutException) {\n        log.warn(\"metadata store timed out; retrying\", e); // retry with backoff\n    } else { throw e; }\n}","handlingStrategy":"try-catch","validationCode":"// check store reachability before iterating\nstore.sync(ledgersRootPath).get(30, TimeUnit.SECONDS);","typeGuard":null,"tryCatchPattern":"try { ... } catch (IOException e) {\n  Throwable cause = e.getCause();\n  if (cause instanceof TimeoutException) { /* retry/backoff */ }\n  else if (Thread.currentThread().isInterrupted()) { return; }\n  else { throw e; }\n}","preventionTips":["Monitor metadata store health before starting ledger scans","Run iteration on threads that are not interrupted at shutdown","Use timeouts generous relative to store latency","Recreate the iterator after transient failures"],"tags":["io","metadata-store","timeout","bookkeeper"],"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-14T00:17:10.932Z"}