apache/iceberg · warning

An error occurred while closing the stream

Error message

An error occurred while closing the stream

What it means

S3InputStream.closeStream aborts and closes the underlying S3 stream; an IOException here is either swallowed with a WARN ('An error occurred while closing the stream') when closeQuietly is set, or rethrown/wrapped unless it is the Apache client's ConnectionClosedException, which is expected after aborting a stream. Developers typically see this as a noisy WARN during normal abort-driven closes or a wrapped IOException when a real close failure occurs.

Source

Thrown at aws/src/main/java/org/apache/iceberg/aws/s3/S3InputStream.java:282

    }
  }

  @VisibleForTesting
  void resetForRetry() throws IOException {
    openStream(true);
  }

  private void closeStream(boolean closeQuietly) throws IOException {
    if (stream != null) {
      // if we aren't at the end of the stream, and the stream is abortable, then
      // call abort() so we don't read the remaining data with the Apache HTTP client
      abortStream();
      try {
        stream.close();
      } catch (IOException e) {
        if (closeQuietly) {
          stream = null;
          LOG.warn("An error occurred while closing the stream", e);
          return;
        }

        // the Apache HTTP client will throw a ConnectionClosedException
        // when closing an aborted stream, which is expected
        if (!e.getClass().getSimpleName().equals("ConnectionClosedException")) {
          throw e;
        }
      }
      stream = null;
    }
  }

  private void abortStream() {
    try {
      if (stream instanceof Abortable && stream.read() != -1) {
        ((Abortable) stream).abort();
      }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Enable/set closeQuietly=true (S3FileIO property aws.s3.stream.close-quietly or constructor flag) if the WARN is noise from aborted streams
  2. Confirm the logged exception is ConnectionClosedException — that is expected after abort and can be ignored
  3. If a different IOException is thrown, check S3 endpoint connectivity, timeouts, and connection pool settings
  4. Retry the read from a fresh stream; the failed stream is already nulled out on quiet close

Example fix

// before
try (S3InputStream in = new S3InputStream(io, bucket, key)) { ... } // noisy close errors after abort
// after
S3InputStream in = new S3InputStream(io, bucket, key, /*closeQuietly=*/true);
try { ... } finally { in.close(); } // abort-close IOExceptions logged as WARN, not thrown
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the reader is closed exactly once and not re-used after close
if (in == null || closed) skipClose(); // S3InputStream nulls stream on quiet close

Try / catch

try {
  in.close();
} catch (IOException e) {
  if ("ConnectionClosedException".equals(e.getClass().getSimpleName())) {
    // expected after aborting an S3 stream — ignore
  } else {
    LOG.warn("real stream close failure", e);
  }
}

Prevention

When it happens

Trigger: Closing an S3InputStream (try-with-resources or explicit close) whose stream was aborted mid-read (e.g. after read failures or early close), or a stream close that fails at the HTTP client level with an IOException other than ConnectionClosedException.

Common situations: Aborting reads of large S3 objects (seek/skip past ranges) producing expected ConnectionClosedException noise; stale/closed connections from long-lived readers; aggressive connection pool eviction; reading objects with short HTTP timeouts then closing.

Related errors


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