{"record":{"id":"98b07b21c3a4eed5","repo":"apache/pulsar","slug":"interrupted-while-preloading","errorCode":null,"errorMessage":"Interrupted while preloading","messagePattern":"Interrupted while preloading","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/LegacyHierarchicalLedgerRangeIterator.java","lineNumber":118,"sourceCode":"        while (nextRange == null && !iteratorDone) {\n            boolean hasMoreElements = false;\n            try {\n                if (l1NodesIter == null) {\n                    List<String> l1Nodes = store.sync(ledgersRoot)\n                            .thenCompose(__ -> store.getChildrenFromStore(ledgersRoot))\n                            .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n                    l1NodesIter = l1Nodes.iterator();\n                    hasMoreElements = nextL1Node();\n                } else if (l2NodesIter == null || !l2NodesIter.hasNext()) {\n                    hasMoreElements = nextL1Node();\n                } else {\n                    hasMoreElements = true;\n                }\n            } catch (ExecutionException | TimeoutException ke) {\n                throw new IOException(\"Error preloading next range\", ke);\n            } catch (InterruptedException ie) {\n                Thread.currentThread().interrupt();\n                throw new IOException(\"Interrupted while preloading\", ie);\n            }\n            if (hasMoreElements) {\n                nextRange = getLedgerRangeByLevel(curL1Nodes, l2NodesIter.next());\n                if (nextRange.size() == 0) {\n                    nextRange = null;\n                }\n            } else {\n                iteratorDone = true;\n            }\n        }\n    }\n\n    @Override\n    public synchronized boolean hasNext() throws IOException {\n        preload();\n        return nextRange != null && !iteratorDone;\n    }\n","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/LegacyHierarchicalLedgerRangeIterator.java#L100-L136","documentation":"IOException 'Interrupted while preloading' thrown by LegacyHierarchicalLedgerRangeIterator.preload when the thread blocking on the metadata-store future is interrupted. The method restores the interrupt flag before throwing, so callers retain correct interruption semantics.","triggerScenarios":"hasNext() triggers preload(); the thread waiting on .get(BLOCKING_CALL_TIMEOUT) is interrupted, typically during shutdown or when the task is cancelled.","commonSituations":"Broker/service shutdown while a ledger-enumeration loop is active; executor shutdownNow() cancelling the worker thread; test timeouts interrupting the test thread.","solutions":["Let shutdown complete cleanly — stop driving the iterator after interruption and exit the loop","Avoid interrupting worker threads mid-enumeration; coordinate shutdown before cancelling tasks","If interruption is unexpected, audit which executor/task lifecycle interrupts this thread"],"exampleFix":"// before\nwhile (it.hasNext()) { ... } // throws IOException 'Interrupted while preloading' on shutdown\n// after\nwhile (!Thread.currentThread().isInterrupted() && it.hasNext()) {\n    ...\n}\n// or handle:\ntry {\n    while (it.hasNext()) { ... }\n} catch (IOException e) {\n    if (Thread.currentThread().isInterrupted()) return; // expected shutdown\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"if (Thread.currentThread().isInterrupted()) { return; /* skip enumeration */ }","typeGuard":null,"tryCatchPattern":"try {\n    while (it.hasNext()) { ... }\n} catch (IOException e) {\n    if (Thread.currentThread().isInterrupted()) {\n        return; // expected during shutdown — do not log as failure\n    }\n    throw e;\n}","preventionTips":["Coordinate shutdown: stop enumeration before shutdownNow()","Check Thread.interrupted() status in loops to exit early","Never run long blocking enumerations on threads subject to cancellation"],"tags":["metadata-store","interruption","iteration"],"backgroundTag":"thread-interrupted","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"}