{"record":{"id":"f91fa6facba1295b","repo":"apache/druid","slug":"no-usable-range-reader-for-partial-segment-s-it","errorCode":null,"errorMessage":"No usable range reader for partial segment[%s]; its local layout has been reclaimed","messagePattern":"No usable range reader for partial segment\\[(.+?)\\]; its local layout has been reclaimed","errorType":"exception","errorClass":"SegmentLoadingException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/segment/loading/SegmentLocalCacheManager.java","lineNumber":1709,"sourceCode":"      catch (Exception e) {\n        log.warn(e, \"Failed to open a range reader for partial segment[%s] during bootstrap\", dataSegment.getId());\n        rangeReader = null;\n      }\n      if (rangeReader == null) {\n        // Anomalous: a layout on disk means range reads worked when it was written, so this should not happen (the\n        // loadSpec is now non-range-capable, or no longer converts to a known type). Reclaim the layout so the next\n        // load fetches it fresh rather than reserving an entry that could never fetch anything. The info file goes\n        // with it: it asserts that this segment has local cache state, which stops being true here, and nothing else\n        // will remove it (no entry was reserved, so there is no unmount hook to fire).\n        log.warn(\n            \"On-disk partial-load layout for segment[%s] in [%s] has no usable range reader (this should not \"\n            + \"happen); deleting it so the segment can be re-loaded.\",\n            dataSegment.getId(),\n            partialDir\n        );\n        atomicMoveAndDeleteCacheEntryDirectory(partialDir);\n        deleteSegmentInfoFile(dataSegment);\n        throw new SegmentLoadingException(\n            \"No usable range reader for partial segment[%s]; its local layout has been reclaimed\",\n            dataSegment.getId()\n        );\n      }\n      final ReservedPartial reserved = tryReservePartialAt(dataSegment, rangeReader, location, false);\n      if (reserved == null) {\n        throw new SegmentLoadingException(\n            \"Failed to reserve partial metadata for segment[%s] on location[%s] during bootstrap\",\n            dataSegment.getId(),\n            location.getPath()\n        );\n      }\n      return reserved.hold;\n    }\n    return null;\n  }\n\n  /**","sourceCodeStart":1691,"sourceCodeEnd":1727,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/segment/loading/SegmentLocalCacheManager.java#L1691-L1727","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: historical starts with no deep-storage extension\n// druid.extensions.loadList=[\"druid-kafka-indexing-service\"]\n// after: add the extension backing the loadSpec scheme\ndruid.extensions.loadList=[\"druid-s3-extensions\"]\ndruid.storage.type=s3","handlingStrategy":"retry","validationCode":"// before bootstrap, ensure deep-storage extension for the loadSpec is on the classpath\ndruid.extensions.loadList=[\"druid-s3-extensions\"] // match your druid.storage.type/loadSpec scheme","typeGuard":null,"tryCatchPattern":"try { manager.bootstrap(); } catch (SegmentLoadingException e) { log.warn(e, \"Segment layout reclaimed; coordinator will re-issue load\"); }","preventionTips":["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."],"tags":["segment-cache","bootstrap","range-reader","deep-storage"],"backgroundTag":"resource-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}