apache/iceberg · warning

Unclosed input stream created by: {}

Error message

Unclosed input stream created by: 
	{}

What it means

OSSInputStream registers its creation stack trace and, in finalize(), if the stream was never closed, it closes it to release the underlying OSSObject and logs a warning showing where the stream was created. This catches leaks — callers who opened stream(...) but never called close() — letting the GC reclaim the resource, while the warning points at the offending call site.

Source

Thrown at aliyun/src/main/java/org/apache/iceberg/aliyun/oss/OSSInputStream.java:167

    GetObjectRequest request = new GetObjectRequest(uri.bucket(), uri.key()).withRange(pos, -1);
    stream = client.getObject(request).getObjectContent();
  }

  private void closeStream() throws IOException {
    if (stream != null) {
      stream.close();
      stream = null;
    }
  }

  @SuppressWarnings({"checkstyle:NoFinalizer", "Finalize", "deprecation"})
  @Override
  protected void finalize() throws Throwable {
    super.finalize();
    if (!closed) {
      close(); // releasing resources is more important than printing the warning
      String trace = Joiner.on("\n\t").join(Arrays.copyOfRange(createStack, 1, createStack.length));
      LOG.warn("Unclosed input stream created by: \n\t{}", trace);
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Wrap every stream in try-with-resources: try (InputStream in = file.newStream()) { ... }.
  2. Use the 'created by' stack trace in the warning to locate the leaked open call and add close/finally there.
  3. For conditional reads, close the stream in all branches, including early returns and exceptions.
  4. Upgrade Iceberg if you see spurious warnings — finalizer-based detection may race; rely on explicit close regardless.

Example fix

// before
InputStream in = file.newStream();
long len = file.getLength();
// after
try (InputStream in = file.newStream()) {
  long len = file.getLength();
}
Defensive patterns

Strategy: try-catch

Try / catch

try (InputStream in = file.newStream()) {
  readAll(in);
} catch (IOException e) {
  throw new UncheckedIOException(e);
} // close() guaranteed on all paths — no finalize warning

Prevention

When it happens

Trigger: Code calls OSSFileIO.newInputFile().newStream() (or OSSInputFile stream()) and never calls close(), letting the stream become garbage-collectible while still open.

Common situations: Missing try-with-resources around stream reads in custom Avro/Parquet readers; exceptions thrown between open and close without finally; stream stored in a field and forgotten during task cancellation.

Related errors


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