{"record":{"id":"b1510df07530fd5b","repo":"apache/iceberg","slug":"failed-to-close-current-writer-b1510d","errorCode":null,"errorMessage":"Failed to close current writer","messagePattern":"Failed to close current writer","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/io/RollingFileWriter.java","lineNumber":128,"sourceCode":"    this.currentFile = newFile();\n    this.currentFileRows = 0;\n    this.currentWriter = newWriter(currentFile);\n  }\n\n  private EncryptedOutputFile newFile() {\n    if (spec.isUnpartitioned() || partition == null) {\n      return fileFactory.newOutputFile();\n    } else {\n      return fileFactory.newOutputFile(spec, partition);\n    }\n  }\n\n  private void closeCurrentWriter() {\n    if (currentWriter != null) {\n      try {\n        currentWriter.close();\n      } catch (IOException e) {\n        throw new UncheckedIOException(\"Failed to close current writer\", e);\n      }\n\n      if (currentFileRows == 0L) {\n        // the file may not have been created or cannot be deleted, and it isn't worth failing\n        // the job to clean up, skip deleting\n        Tasks.foreach(currentFile.encryptingOutputFile())\n            .suppressFailureWhenFinished()\n            .onFailure(\n                (file, exc) ->\n                    LOG.warn(\n                        \"Failed to delete the uncommitted empty file during writer clean up: {}\",\n                        file,\n                        exc))\n            .run(io::deleteFile);\n      } else {\n        addResult(currentWriter.result());\n      }\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/io/RollingFileWriter.java#L110-L146","documentation":"RollingFileWriter.closeCurrentWriter wraps IOException from closing the underlying data writer in UncheckedIOException. It means the currently open data file could not be flushed/closed (e.g. the output stream failed), and the write is aborted rather than committing a possibly corrupt file.","triggerScenarios":"Calling write() to roll to a new file or close() at the end of writing, when the underlying Avro/Parquet/ORC writer's close() throws IOException — disk full, network failure to object store, or the output stream already aborted.","commonSituations":"Object-store throttling or credential expiry mid-write; disk quota exceeded on local executor storage; task preemption killing the underlying stream; transient network partition to storage backend.","solutions":["Check storage connectivity/credentials and retry the failed write task.","Verify sufficient disk space and inode/quota limits on the write volume.","Inspect the wrapped IOException cause for the root storage error (e.g. S3 503, GCS quota).","Re-run the job; if transient throttling is frequent, tune object-store client retry settings."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-check storage writability before the job\ntry (OutputStream os = fileIO.newOutputFile(stagingPath).create()) {\n  os.write(1); // fail fast if storage unreachable\n}","typeGuard":null,"tryCatchPattern":"try {\n  writer.close();\n} catch (UncheckedIOException e) {\n  IOException cause = e.getCause();\n  if (isTransient(cause)) { retryTask(); } else { throw e; }\n}","preventionTips":["Monitor disk space and object-store error rates on executors","Configure object-store client retries and generous timeouts for the storage backend","Keep credentials fresh/rotated so long tasks do not hit expiry mid-close"],"tags":["io","file-write-failed","unchecked-ioexception"],"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"}