apache/druid · warning · IOException

Interrupted while waiting for mount

Error message

Interrupted while waiting for mount

What it means

PartialSegmentMetadataCacheEntry.awaitMount waits on the Future completing the metadata mount. An interrupt while blocked in future.get() is converted to an IOException after re-asserting the thread's interrupt flag, since the mount outcome is unknowable at that point.

Solutions

  1. Respect the restored interrupt flag and abort the current load; rely on the coordinator's load queue to retry the segment.
  2. Make shutdown paths drain in-flight mounts before interrupting worker threads.
  3. Investigate sources of spurious interrupts if this occurs outside shutdown.
Defensive patterns

Strategy: try-catch

Validate before calling

if (Thread.currentThread().isInterrupted()) {
  throw new InterruptedException();
}

Try / catch

try {
  metadata.mount(location);
} catch (IOException e) {
  if (e.getCause() instanceof InterruptedException || Thread.currentThread().isInterrupted()) {
    Thread.currentThread().interrupt();
    return; // abort; load queue will retry
  }
  throw e;
}

Prevention

When it happens

Trigger: A thread calling mount() on a PartialSegmentMetadataCacheEntry receives Thread.interrupt() while blocked in future.get() awaiting the async metadata mount.

Common situations: Node shutdown or task cancellation while a partial-load rule mount is in progress; coordinator issuing concurrent drops and loads; thread pool termination during reload.

Related errors


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

Appendix: source

Thrown at server/src/main/java/org/apache/druid/segment/loading/PartialSegmentMetadataCacheEntry.java:1062

          allPresent = false;
          break;
        }
      }
      if (allPresent) {
        restorable.add(bundleName);
      }
    }
    return restorable;
  }

  private static void awaitMount(SettableFuture<Void> future) throws IOException
  {
    try {
      future.get();
    }
    catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new IOException("Interrupted while waiting for mount", e);
    }
    catch (ExecutionException e) {
      final Throwable cause = e.getCause() == null ? e : e.getCause();
      switch (cause) {
        case IOException ioException -> throw ioException;
        case RuntimeException runtimeException -> throw runtimeException;
        case Error error -> throw error;
        default -> throw DruidException.defensive(e, "mount failed");
      }
    }
  }

  /**
   * Triggers cleanup of this entry. If any references acquired via {@link #acquireMetadataReference()} are still
   * outstanding, the actual unmap-and-delete work is deferred until the last reference releases; in that case this
   * method returns immediately and {@link #doActualUnmount} will fire later on the thread that closes the last
   * reference. With no outstanding references, cleanup runs synchronously on the caller's thread.
   * <p>

View on GitHub (pinned to 9b90983fd2)