apache/iceberg · warning

Interrupted while shutting down pool. Some clients may not…

Error message

Interrupted while shutting down pool. Some clients may not be closed.

What it means

ClientPoolImpl.close() waits (with a timeout) for queued client-connection tasks to finish while shutting down the pool. If the shutdown thread is interrupted while waiting, the pool logs this warning and gives up waiting, so some pooled clients may remain unclosed.

Solutions

  1. Avoid interrupting threads that own the pool; let close() finish before cancelling work.
  2. Close the pool explicitly (try-with-resources or lifecycle hook) instead of relying on finalize.
  3. Restore the interrupt status in your own code and re-check pool state (isClosed()) before reuse.
  4. Check for task cancellation storms; guard pool sharing across cancelled tasks.

Example fix

// before
new Thread(() -> pool.close()).interrupt();
// after
Thread t = new Thread(pool::close);
t.start();
t.join(); // do not interrupt while shutting down
Defensive patterns

Strategy: try-catch

Validate before calling

if (pool.isClosed()) throw new IllegalStateException("Pool already closed");

Try / catch

try { pool.close(); } catch (RuntimeException e) { LOG.warn("pool close issue", e); Thread.currentThread().interrupt(); }

Prevention

When it happens

Trigger: Closing a ClientPool (directly or via finalize/try-with-resources) from a thread that is interrupted during the join/wait on queued client-close tasks.

Common situations: Cancelling a Spark/Flink task that owns the pool, JVM shutdown hooks interrupting threads, mismanaged executor lifecycle, or double-close during finalize racing with explicit close.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/0b584ca7bbc830fe. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/ClientPoolImpl.java:131

          synchronized (this) {
            if (!clients.isEmpty()) {
              C client = clients.removeFirst();
              close(client);
              currentSize -= 1;
            }
          }
        }
        if (clients.isEmpty() && currentSize > 0) {
          // wake every second in case this missed the signal
          synchronized (signal) {
            signal.wait(1000);
          }
        }
      }

    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      LOG.warn("Interrupted while shutting down pool. Some clients may not be closed.", e);
    }
  }

  private C get() throws InterruptedException {
    Preconditions.checkState(!closed, "Cannot get a client from a closed pool");
    while (true) {
      if (!clients.isEmpty() || currentSize < poolSize) {
        synchronized (this) {
          if (!clients.isEmpty()) {
            return clients.removeFirst();
          } else if (currentSize < poolSize) {
            C client = newClient();
            currentSize += 1;
            return client;
          }
        }
      }
      synchronized (signal) {

View on GitHub (pinned to 86d9c8fc54)