apache/druid · error · SegmentLoadingException

Stale non-partial cache entry

Error message

Stale non-partial cache entry[%s] at id[%s] on location[%s] blocks partial-load reservation and is currently held; the coordinator's load queue will retry

What it means

When reserving an id for a partial load, SegmentLocalCacheManager may find a stale non-partial (complete) cache entry occupying that id. If it cannot be evicted because it is currently held by another user, eviction fails and this SegmentLoadingException is thrown; the coordinator's load queue will retry the load later.

Solutions

  1. Wait and let the coordinator's load queue retry once the stale entry's holders release it.
  2. Drop the complete segment (via coordinator drop rules) so the cache entry is released before applying the partial-load rule.
  3. Check for long-running queries or leaked references holding the old entry; reduce their lifetime.
  4. Restart or drop the cache location if the entry is genuinely orphaned yet incorrectly reported as held.
Defensive patterns

Strategy: retry

Validate before calling

// before triggering partial load, check the id is not held as a complete entry
final CacheEntry existing = location.getCacheEntry(segmentId);
if (existing != null && !(existing instanceof PartialSegmentMetadataCacheEntry)) {
  LOGGER.warn("Segment %s is cached as complete; drop it before applying partial-load rule", segmentId);
}

Type guard

static boolean isStaleNonPartialBlocker(final CacheEntry entry) {
  return entry != null && !(entry instanceof PartialSegmentMetadataCacheEntry);
}

Try / catch

try {
  cacheManager.loadPartial(segment, rule);
} catch (SegmentLoadingException e) {
  if (e.getMessage() != null && e.getMessage().contains("blocks partial-load reservation")) {
    // transient: wait for holders to release, coordinator will retry with backoff
    scheduler.schedule(this::retryLoad, 30, TimeUnit.SECONDS);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: loadPartial or reapplyRuleFromInfoFile encounters a non-partial CacheEntry at the target id, calls location.removeUnheldWeakEntry, and getCacheEntry still returns a held entry afterward.

Common situations: The same segment id was previously loaded as a complete segment and is still referenced (e.g. by an open query or cursor) when a partial-load rule tries to reserve it; lingering references preventing weak-entry removal.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at server/src/main/java/org/apache/druid/segment/loading/SegmentLocalCacheManager.java:792

   * evicting the stale entry first).
   * <p>
   * {@link StorageLocation#removeUnheldWeakEntry} is a no-op when the entry is held (in-flight query), so we
   * detect via {@link StorageLocation#getCacheEntry} whether eviction actually happened. If not, throw a retryable
   * {@link SegmentLoadingException}: the coordinator's load queue retries on the next sync, and by then the query
   * should have released the hold and eviction will succeed.
   */
  private void evictStaleNonPartialWeakEntry(SegmentId segmentId) throws SegmentLoadingException
  {
    final SegmentCacheEntryIdentifier id = new SegmentCacheEntryIdentifier(segmentId);
    for (StorageLocation location : locations) {
      final CacheEntry entry = location.getCacheEntry(id);
      if (entry == null || entry instanceof PartialSegmentMetadataCacheEntry) {
        continue;
      }
      location.removeUnheldWeakEntry(id);
      final CacheEntry stillThere = location.getCacheEntry(id);
      if (stillThere != null) {
        throw new SegmentLoadingException(
            "Stale non-partial cache entry[%s] at id[%s] on location[%s] blocks partial-load reservation and is "
            + "currently held; the coordinator's load queue will retry",
            stillThere.getClass().getSimpleName(),
            id,
            location.getPath()
        );
      }
      log.info(
          "Evicted stale non-partial cache entry[%s] at location[%s] to make room for partial-load rule on "
          + "segment[%s]",
          entry.getClass().getSimpleName(),
          location.getPath(),
          segmentId
      );
    }
  }

  /**

View on GitHub (pinned to 9b90983fd2)