{"record":{"id":"c3b21539fb76f49f","repo":"apache/iceberg","slug":"unclosed-input-stream-created-by","errorCode":null,"errorMessage":"Unclosed input stream created by: \n\t{}","messagePattern":"Unclosed input stream created by: \n\t(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"aliyun/src/main/java/org/apache/iceberg/aliyun/oss/OSSInputStream.java","lineNumber":167,"sourceCode":"    GetObjectRequest request = new GetObjectRequest(uri.bucket(), uri.key()).withRange(pos, -1);\n    stream = client.getObject(request).getObjectContent();\n  }\n\n  private void closeStream() throws IOException {\n    if (stream != null) {\n      stream.close();\n      stream = null;\n    }\n  }\n\n  @SuppressWarnings({\"checkstyle:NoFinalizer\", \"Finalize\", \"deprecation\"})\n  @Override\n  protected void finalize() throws Throwable {\n    super.finalize();\n    if (!closed) {\n      close(); // releasing resources is more important than printing the warning\n      String trace = Joiner.on(\"\\n\\t\").join(Arrays.copyOfRange(createStack, 1, createStack.length));\n      LOG.warn(\"Unclosed input stream created by: \\n\\t{}\", trace);\n    }\n  }\n}\n","sourceCodeStart":149,"sourceCodeEnd":171,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/aliyun/src/main/java/org/apache/iceberg/aliyun/oss/OSSInputStream.java#L149-L171","documentation":"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.","triggerScenarios":"Code calls OSSFileIO.newInputFile().newStream() (or OSSInputFile stream()) and never calls close(), letting the stream become garbage-collectible while still open.","commonSituations":"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.","solutions":["Wrap every stream in try-with-resources: try (InputStream in = file.newStream()) { ... }.","Use the 'created by' stack trace in the warning to locate the leaked open call and add close/finally there.","For conditional reads, close the stream in all branches, including early returns and exceptions.","Upgrade Iceberg if you see spurious warnings — finalizer-based detection may race; rely on explicit close regardless."],"exampleFix":"// before\nInputStream in = file.newStream();\nlong len = file.getLength();\n// after\ntry (InputStream in = file.newStream()) {\n  long len = file.getLength();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try (InputStream in = file.newStream()) {\n  readAll(in);\n} catch (IOException e) {\n  throw new UncheckedIOException(e);\n} // close() guaranteed on all paths — no finalize warning","preventionTips":["Always use try-with-resources for streams from FileIO.newInputFile().newStream().","Never store an open InputStream in a long-lived field or cache entry.","In error paths, close streams in finally rather than letting the exception bypass close.","Treat any 'Unclosed input stream created by' warning as a real leak to fix at the traced call site, not noise."],"tags":["aliyun","oss","resource-leak","inputstream","finalizer"],"backgroundTag":"unclosed-resource-leak","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}