{"record":{"id":"f25ca7b528902334","repo":"apache/druid","slug":"stale-non-partial-cache-entry-s-at-id-s-on-loc","errorCode":null,"errorMessage":"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","messagePattern":"Stale non-partial cache entry\\[(.+?)\\] at id\\[(.+?)\\] on location\\[(.+?)\\] blocks partial-load reservation and is currently held; the coordinator's load queue will retry","errorType":"exception","errorClass":"SegmentLoadingException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/segment/loading/SegmentLocalCacheManager.java","lineNumber":792,"sourceCode":"   * evicting the stale entry first).\n   * <p>\n   * {@link StorageLocation#removeUnheldWeakEntry} is a no-op when the entry is held (in-flight query), so we\n   * detect via {@link StorageLocation#getCacheEntry} whether eviction actually happened. If not, throw a retryable\n   * {@link SegmentLoadingException}: the coordinator's load queue retries on the next sync, and by then the query\n   * should have released the hold and eviction will succeed.\n   */\n  private void evictStaleNonPartialWeakEntry(SegmentId segmentId) throws SegmentLoadingException\n  {\n    final SegmentCacheEntryIdentifier id = new SegmentCacheEntryIdentifier(segmentId);\n    for (StorageLocation location : locations) {\n      final CacheEntry entry = location.getCacheEntry(id);\n      if (entry == null || entry instanceof PartialSegmentMetadataCacheEntry) {\n        continue;\n      }\n      location.removeUnheldWeakEntry(id);\n      final CacheEntry stillThere = location.getCacheEntry(id);\n      if (stillThere != null) {\n        throw new SegmentLoadingException(\n            \"Stale non-partial cache entry[%s] at id[%s] on location[%s] blocks partial-load reservation and is \"\n            + \"currently held; the coordinator's load queue will retry\",\n            stillThere.getClass().getSimpleName(),\n            id,\n            location.getPath()\n        );\n      }\n      log.info(\n          \"Evicted stale non-partial cache entry[%s] at location[%s] to make room for partial-load rule on \"\n          + \"segment[%s]\",\n          entry.getClass().getSimpleName(),\n          location.getPath(),\n          segmentId\n      );\n    }\n  }\n\n  /**","sourceCodeStart":774,"sourceCodeEnd":810,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/segment/loading/SegmentLocalCacheManager.java#L774-L810","documentation":"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.","triggerScenarios":"loadPartial or reapplyRuleFromInfoFile encounters a non-partial CacheEntry at the target id, calls location.removeUnheldWeakEntry, and getCacheEntry still returns a held entry afterward.","commonSituations":"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.","solutions":["Wait and let the coordinator's load queue retry once the stale entry's holders release it.","Drop the complete segment (via coordinator drop rules) so the cache entry is released before applying the partial-load rule.","Check for long-running queries or leaked references holding the old entry; reduce their lifetime.","Restart or drop the cache location if the entry is genuinely orphaned yet incorrectly reported as held."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before triggering partial load, check the id is not held as a complete entry\nfinal CacheEntry existing = location.getCacheEntry(segmentId);\nif (existing != null && !(existing instanceof PartialSegmentMetadataCacheEntry)) {\n  LOGGER.warn(\"Segment %s is cached as complete; drop it before applying partial-load rule\", segmentId);\n}","typeGuard":"static boolean isStaleNonPartialBlocker(final CacheEntry entry) {\n  return entry != null && !(entry instanceof PartialSegmentMetadataCacheEntry);\n}","tryCatchPattern":"try {\n  cacheManager.loadPartial(segment, rule);\n} catch (SegmentLoadingException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"blocks partial-load reservation\")) {\n    // transient: wait for holders to release, coordinator will retry with backoff\n    scheduler.schedule(this::retryLoad, 30, TimeUnit.SECONDS);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Drop complete versions of a segment before applying partial-load rules to the same id.","Minimize long-held references (open queries/cursors) to segments slated for partial loading.","Monitor for leaked cache-entry holds; investigate entries never released.","Let the coordinator's load-queue backoff handle retries instead of immediate re-triggering."],"tags":["cache-conflict","segment-loading","partial-load","contention"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}