{"record":{"id":"9d068b2ccdc0d30e","repo":"apache/iceberg","slug":"failed-calling-close","errorCode":null,"errorMessage":"Failed calling close","messagePattern":"Failed calling close","errorType":"exception","errorClass":"RuntimeIOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/util/Exceptions.java","lineNumber":33,"sourceCode":" * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\npackage org.apache.iceberg.util;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport org.apache.iceberg.exceptions.RuntimeIOException;\n\npublic class Exceptions {\n  private Exceptions() {}\n\n  public static void close(Closeable closeable, boolean suppressExceptions) {\n    try {\n      closeable.close();\n    } catch (IOException e) {\n      if (!suppressExceptions) {\n        throw new RuntimeIOException(e, \"Failed calling close\");\n      }\n      // otherwise, ignore the exception\n    }\n  }\n\n  public static <E extends Exception> E suppressExceptions(E alreadyThrown, Runnable run) {\n    try {\n      run.run();\n    } catch (Exception e) {\n      alreadyThrown.addSuppressed(e);\n    }\n    return alreadyThrown;\n  }\n\n  public static <E extends Exception> void suppressAndThrow(E alreadyThrown, Runnable run)\n      throws E {\n    throw suppressExceptions(alreadyThrown, run);\n  }","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/util/Exceptions.java#L15-L51","documentation":"Exceptions.close(Closeable, boolean) wraps any IOException thrown while closing a resource into a RuntimeIOException with message 'Failed calling close', unless suppression is requested. It surfaces close-time failures instead of silently swallowing them.","triggerScenarios":"Calling Exceptions.close(closeable, false) where the underlying stream's close() throws IOException — e.g., flushing buffered data to a failed file system or network target during close.","commonSituations":"Closing a Parquet/Avro writer whose output stream hits a disk-full or permission error; closing Hadoop/LocalInputFile streams in error paths where the original exception gets replaced or masked by this close failure.","solutions":["Check the underlying storage for space/permission/connectivity problems indicated by the wrapped cause","Use suppressExceptions=true for cleanup code that must not mask the primary failure","Close resources with try-with-resources so the close exception is properly suppressed alongside the main exception"],"exampleFix":"// before\nExceptions.close(stream, false); // may mask primary failure\n// after\ntry {\n  // primary work\n} finally {\n  Exceptions.close(stream, true);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { Exceptions.close(closeable, false); } catch (RuntimeIOException e) { LOG.warn(\"close failed\", e.getCause()); }","preventionTips":["Use suppressExceptions=true in finally blocks to avoid masking primary failures","Prefer try-with-resources for AutoCloseable resources","Monitor disk space and permissions for output targets"],"tags":["io","close","resources"],"backgroundTag":"file-write-failed","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"}