apache/druid · error · SegmentLoadingException
No usable range reader for partial segment[%s]; its local la
Error message
No usable range reader for partial segment[%s]; its local layout has been reclaimed
What it means
Thrown by SegmentLocalCacheManager.reservePartialForBootstrap during cache bootstrap when an on-disk partial-load layout exists for a segment, but no SegmentRangeReader can be opened for it. Since range reads must have worked when the layout was written, this is anomalous: it indicates the segment's loadSpec is no longer range-capable or no longer converts to a known type. The manager deletes the stale layout and info file so the segment can be re-fetched, and fails the segment so the coordinator re-issues the load.
Source
Thrown at server/src/main/java/org/apache/druid/segment/loading/SegmentLocalCacheManager.java:1709
catch (Exception e) {
log.warn(e, "Failed to open a range reader for partial segment[%s] during bootstrap", dataSegment.getId());
rangeReader = null;
}
if (rangeReader == null) {
// Anomalous: a layout on disk means range reads worked when it was written, so this should not happen (the
// loadSpec is now non-range-capable, or no longer converts to a known type). Reclaim the layout so the next
// load fetches it fresh rather than reserving an entry that could never fetch anything. The info file goes
// with it: it asserts that this segment has local cache state, which stops being true here, and nothing else
// will remove it (no entry was reserved, so there is no unmount hook to fire).
log.warn(
"On-disk partial-load layout for segment[%s] in [%s] has no usable range reader (this should not "
+ "happen); deleting it so the segment can be re-loaded.",
dataSegment.getId(),
partialDir
);
atomicMoveAndDeleteCacheEntryDirectory(partialDir);
deleteSegmentInfoFile(dataSegment);
throw new SegmentLoadingException(
"No usable range reader for partial segment[%s]; its local layout has been reclaimed",
dataSegment.getId()
);
}
final ReservedPartial reserved = tryReservePartialAt(dataSegment, rangeReader, location, false);
if (reserved == null) {
throw new SegmentLoadingException(
"Failed to reserve partial metadata for segment[%s] on location[%s] during bootstrap",
dataSegment.getId(),
location.getPath()
);
}
return reserved.hold;
}
return null;
}
/**View on GitHub (pinned to 9b90983fd2)
Solutions
- Ensure the deep-storage extension matching the segment's loadSpec type is loaded and configured (e.g. druid-s3-extensions, google cloud storage extension).
- Check runtime.properties for druid.storage.type and verify the loadSpec of the affected segment matches an available scheme.
- The layout is automatically reclaimed; verify the coordinator re-issues the load and the segment re-downloads fresh — if not, manually delete the stale segment directory and info file under the cache location.
- Restart the historical node after fixing extension config so bootstrap retries cleanly.
Example fix
// before: historical starts with no deep-storage extension // druid.extensions.loadList=["druid-kafka-indexing-service"] // after: add the extension backing the loadSpec scheme druid.extensions.loadList=["druid-s3-extensions"] druid.storage.type=s3
Defensive patterns
Strategy: retry
Validate before calling
// before bootstrap, ensure deep-storage extension for the loadSpec is on the classpath druid.extensions.loadList=["druid-s3-extensions"] // match your druid.storage.type/loadSpec scheme
Try / catch
try { manager.bootstrap(); } catch (SegmentLoadingException e) { log.warn(e, "Segment layout reclaimed; coordinator will re-issue load"); } Prevention
- Keep deep-storage extensions and loadSpec schemes consistent across rolling upgrades.
- Avoid carrying cache directories across installations with different storage types.
- Monitor bootstrap warnings about partial layouts to catch loadSpec mismatches early.
When it happens
Trigger: Cache bootstrap scans a location, finds a partial segment directory (PartialSegmentFileMapperV10 layout with V10 index file), and tryOpenRangeReader returns null/throws because the segment's loadSpec cannot provide range reads (e.g. loadSpec type no longer registered, deep-storage scheme changed).
Common situations: Upgrading/changing Druid extensions so deep-storage loadSpec types (e.g. S3/GCS/HDFS) are no longer configured; a hand-edited or migrated segment info file with an unconvertible loadSpec; cache directories carried over from an installation with different range-read support.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Failed to open range reader for segment[%s]
- Failed to reserve partial metadata for segment[%s] on locati
- Location[%s] with available bytes[%,d] cannot reserve segmen
- Couldn't delete segments from Azure. See the task logs for m
- e.getMessage()
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/f91fa6facba1295b.
Report an issue: GitHub.