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

  1. Ensure the deep-storage extension matching the segment's loadSpec type is loaded and configured (e.g. druid-s3-extensions, google cloud storage extension).
  2. Check runtime.properties for druid.storage.type and verify the loadSpec of the affected segment matches an available scheme.
  3. 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.
  4. 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

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


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/f91fa6facba1295b. Report an issue: GitHub.