{"record":{"id":"03d63328ce129cba","repo":"apache/iceberg","slug":"failed-to-write-manifest-list-file","errorCode":null,"errorMessage":"Failed to write manifest list file","messagePattern":"Failed to write manifest list file","errorType":"exception","errorClass":"RuntimeIOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/SnapshotProducer.java","lineNumber":329,"sourceCode":"            parentSnapshotId,\n            sequenceNumber,\n            base.nextRowId());\n\n    try (writer) {\n      // keep track of the manifest lists created\n      manifestLists.add(manifestList.location());\n\n      ManifestFile[] manifestFiles = new ManifestFile[manifests.size()];\n\n      Tasks.range(manifestFiles.length)\n          .stopOnFailure()\n          .throwFailureWhenFinished()\n          .executeWith(workerPool())\n          .run(index -> manifestFiles[index] = manifestsWithMetadata.get(manifests.get(index)));\n\n      writer.addAll(Arrays.asList(manifestFiles));\n    } catch (IOException e) {\n      throw new RuntimeIOException(e, \"Failed to write manifest list file\");\n    }\n\n    Long nextRowId = null;\n    Long assignedRows = null;\n    if (base.formatVersion() >= 3) {\n      nextRowId = base.nextRowId();\n      assignedRows = writer.nextRowId() - base.nextRowId();\n    }\n\n    Map<String, String> summary = summary();\n    String operation = operation();\n\n    if (summary != null && DataOperations.REPLACE.equals(operation)) {\n      long addedRecords =\n          PropertyUtil.propertyAsLong(summary, SnapshotSummary.ADDED_RECORDS_PROP, 0L);\n      long replacedRecords =\n          PropertyUtil.propertyAsLong(summary, SnapshotSummary.DELETED_RECORDS_PROP, 0L);\n","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/SnapshotProducer.java#L311-L347","documentation":"SnapshotProducer.apply() writes the new snapshot's manifest list (an Avro file listing all manifests) to the table's FileIO. When the Avro writer closes with an IOException, it is rethrown as RuntimeIOException with this message. It means the metadata file for the snapshot could not be persisted, so no commit metadata was produced.","triggerScenarios":"Calling table.newSnapshot()/fastAppend()/rewrite-style operations and calling apply()/commit() when the underlying FileIO cannot create or write the manifest-list Avro file: bad location/URI, missing credentials, full disk, or transient object-store failure.","commonSituations":"S3/GCS credentials expired or misconfigured (no permission on the metadata location); warehouse path typo or wrong scheme in catalog configuration; disk full on HDFS/local FS; bucket throttling during large commits; network blip between driver and object store.","solutions":["Check FileIO/catalog configuration (warehouse URI, bucket, credentials) and verify the metadata location is writable.","Retry the commit; object-store throttling and transient network errors are common root causes.","Inspect the cause chain (RuntimeIOException.getCause()) for the underlying IOException to identify storage-side details.","Free disk space or fix HDFS capacity/quota if writing to local or HDFS storage."],"exampleFix":"// before\nTable table = catalog.loadTable(\"db.tbl\");\ntable.newFastAppend().appendFile(df).commit(); // fails: wrong io impl for s3:// path\n// after\nCatalog catalog = CatalogUtil.loadCatalog(\n    \"org.apache.iceberg.rest.RESTCatalog\", \"prod\", \"2\", propsWithS3FileIO);\nTable table = catalog.loadTable(\"db.tbl\");\ntable.newFastAppend().appendFile(df).commit();","handlingStrategy":"try-catch","validationCode":"// verify the table's metadata location is writable before committing\ntry (var f = table.io().create(table.location() + \"/.write_probe.tmp\")) { /* ok */ }","typeGuard":null,"tryCatchPattern":"try {\n  table.newFastAppend().appendFile(df).commit();\n} catch (RuntimeIOException e) {\n  if (e.getCause() instanceof IOException io) {\n    // inspect io for storage-side cause, then retry with backoff\n    Tasks.foreach(() -> commitOp()).retry(3).exponentialBackoff(100, 4);\n  } else throw e;\n}","preventionTips":["Validate catalog/FileIO configuration (warehouse URI, credentials) in a smoke test before jobs run.","Monitor metadata volume disk usage and cloud quotas.","Use object-store versioning to make transient failures recoverable.","Wrap commits in retry with exponential backoff for transient storage faults."],"tags":["io","commit","metadata","runtime-io-exception"],"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"}