apache/druid · error · IllegalStateException

Already closed

Error message

Already closed

What it means

CloseableResourceHolder wraps a lazily-created or shared resource that becomes null once closed. get() refuses to return after close() so callers never use a freed resource, throwing ISE('Already closed').

Solutions

  1. Obtain the resource before close() and keep your own reference
  2. Fix lifecycle ordering so consumers stop before the holder is closed
  3. Guard with isAvailable()/null-check semantics via the holder API if offered
  4. Do not cache the holder across shutdown boundaries

Example fix

// before
holder.close();
Resource r = holder.get(); // ISE
// after
Resource r = holder.get();
holder.close();
Defensive patterns

Strategy: type-guard

Validate before calling

// acquire the resource before close
T res = holder.get(); // then use res after close only if you kept this reference

Type guard

boolean usable = (holder != null); // then call get() before close(); after close(), get() throws by design
// prefer: T res = holder.get(); /* before close */ 

Try / catch

try {
  T res = holder.get();
} catch (ISE e) {
  if ("Already closed".equals(e.getMessage())) { /* holder was closed; reacquire or skip */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling get() on the holder after close() has been invoked (e.g. using the holder's resource after a service's lifecycle close, or a double-close followed by use).

Common situations: Extension/service shutdown ordering where a component still holds the holder and fetches the resource during teardown; caching the holder in a longer-lived object.

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/ea520ce7fdf70738. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/collections/CloseableResourceHolder.java:46

public class CloseableResourceHolder<T extends Closeable> implements ResourceHolder<T>
{
  private final AtomicReference<T> resource;

  /**
   * Use {@link ResourceHolder#fromCloseable}.
   */
  CloseableResourceHolder(T resource)
  {
    this.resource = new AtomicReference<>(Preconditions.checkNotNull(resource, "resource"));
  }

  @Override
  public T get()
  {
    final T retVal = resource.get();
    if (retVal == null) {
      throw new ISE("Already closed");
    }
    return retVal;
  }

  @Override
  public void close()
  {
    final T oldResource = resource.getAndSet(null);
    CloseableUtils.closeAndWrapExceptions(oldResource);
  }
}

View on GitHub (pinned to 9b90983fd2)