apache/druid · error · NoSuchElementException
NoSuchElementException
Error message
NoSuchElementException
What it means
Java standard NoSuchElementException thrown by AzureCloudBlobIterator.next() when the iterator has no more blob items (currentBlobItem == null), violating the Iterator contract by calling next() past the end instead of using hasNext().
Source
Thrown at extensions-core/azure-extensions/src/main/java/org/apache/druid/storage/azure/AzureCloudBlobIterator.java:88
if (prefixesIterator.hasNext()) {
prepareNextRequest();
fetchNextBatch();
advanceBlobItem();
}
}
@Override
public boolean hasNext()
{
return currentBlobItem != null;
}
@Override
public CloudBlobHolder next()
{
if (currentBlobItem == null) {
throw new NoSuchElementException();
}
final CloudBlobHolder retVal = currentBlobItem;
advanceBlobItem();
return retVal;
}
private void prepareNextRequest()
{
URI currentUri = prefixesIterator.next();
if (currentUri.getScheme().equals(AzureStorageAccountInputSource.SCHEME)) {
CloudObjectLocation cloudObjectLocation = new CloudObjectLocation(currentUri);
Pair<String, String> containerInfo = AzureStorageAccountInputSource.getContainerAndPathFromObjectLocation(cloudObjectLocation);
currentStorageAccount = cloudObjectLocation.getBucket();
currentContainer = containerInfo.lhs;
currentPrefix = containerInfo.rhs;
} else {View on GitHub (pinned to 9b90983fd2)
Solutions
- Always guard with hasNext() before calling next()
- Handle the empty-prefix case explicitly before iterating
- Check the prefix/container name if you expected results — an empty list usually means a wrong path
- Ensure a single thread consumes the iterator; it is not thread-safe
Example fix
// before
CloudBlobHolder holder = iterator.next();
// after
if (iterator.hasNext()) {
CloudBlobHolder holder = iterator.next();
} else {
// handle empty result set
} Defensive patterns
Strategy: type-guard
Validate before calling
// check for results before iterating
if (!iterator.hasNext()) {
LOG.info("No blobs under prefix");
return Collections.emptyList();
} Type guard
boolean hasCurrent(Iterator<CloudBlobHolder> it) {
return it != null && it.hasNext();
} Try / catch
try {
CloudBlobHolder holder = iterator.next();
} catch (NoSuchElementException e) {
LOG.warn("Iteration advanced past end; check hasNext() usage", e);
} Prevention
- Always iterate with while (it.hasNext()) { it.next(); }
- Log prefix/container listing counts to detect unexpectedly empty listings
- Never share a single iterator across threads
- Handle empty-prefix cases explicitly in ingestion code
When it happens
Trigger: Calling next() after hasNext() returned false, or calling next() before the first successful fetchNextBatch populated currentBlobItem — e.g., an empty prefix with no blobs, or a loop that ignores hasNext().
Common situations: Listing an Azure container prefix that matches zero blobs; code that assumes at least one result; off-by-one loops iterating exactly blobCount+1 times; concurrent iteration/modification of the underlying batch list.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Recoverable exception
- Failed to get blob item from Azure container[%s], prefix[%s
- Couldn't delete segments from Azure. See the task logs for m
- Couldn't kill segment[%s]: [%s]
- Cannot delete all segment files since Azure Deep Storage sin
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/f92e484dfdddfb1e.
Report an issue: GitHub.