apache/pulsar · warning · IOException
Interrupted while preloading
Error message
Interrupted while preloading
What it means
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.
Source
Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/LegacyHierarchicalLedgerRangeIterator.java:118
while (nextRange == null && !iteratorDone) {
boolean hasMoreElements = false;
try {
if (l1NodesIter == null) {
List<String> l1Nodes = store.sync(ledgersRoot)
.thenCompose(__ -> store.getChildrenFromStore(ledgersRoot))
.get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);
l1NodesIter = l1Nodes.iterator();
hasMoreElements = nextL1Node();
} else if (l2NodesIter == null || !l2NodesIter.hasNext()) {
hasMoreElements = nextL1Node();
} else {
hasMoreElements = true;
}
} catch (ExecutionException | TimeoutException ke) {
throw new IOException("Error preloading next range", ke);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted while preloading", ie);
}
if (hasMoreElements) {
nextRange = getLedgerRangeByLevel(curL1Nodes, l2NodesIter.next());
if (nextRange.size() == 0) {
nextRange = null;
}
} else {
iteratorDone = true;
}
}
}
@Override
public synchronized boolean hasNext() throws IOException {
preload();
return nextRange != null && !iteratorDone;
}
View on GitHub (pinned to 820761864e)
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
Example fix
// before
while (it.hasNext()) { ... } // throws IOException 'Interrupted while preloading' on shutdown
// after
while (!Thread.currentThread().isInterrupted() && it.hasNext()) {
...
}
// or handle:
try {
while (it.hasNext()) { ... }
} catch (IOException e) {
if (Thread.currentThread().isInterrupted()) return; // expected shutdown
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (Thread.currentThread().isInterrupted()) { return; /* skip enumeration */ } Try / catch
try {
while (it.hasNext()) { ... }
} catch (IOException e) {
if (Thread.currentThread().isInterrupted()) {
return; // expected during shutdown — do not log as failure
}
throw e;
} Prevention
- 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
When it happens
Trigger: hasNext() triggers preload(); the thread waiting on .get(BLOCKING_CALL_TIMEOUT) is interrupted, typically during shutdown or when the task is cancelled.
Common situations: Broker/service shutdown while a ledger-enumeration loop is active; executor shutdownNow() cancelling the worker thread; test timeouts interrupting the test thread.
Related errors
- Error preloading next range
- Interrupted while contacting metadata store
- Metadata store address argument is required (--metadata-stor
- Failed to validate global cluster configuration
- Concurrent modification
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/98b07b21c3a4eed5.
Report an issue: GitHub.