apache/iceberg · error · RuntimeIOException

Failed to write delete manifests

Error message

Failed to write delete manifests

What it means

Analogous to the data-manifest writer, writeDeleteManifests produces manifests listing delete (position/deequality) files for v2+ tables. An IOException during writing is rethrown as RuntimeIOException with this message. The delete-capable snapshot cannot be built without these manifests.

Source

Thrown at core/src/main/java/org/apache/iceberg/SnapshotProducer.java:796

    int groupCount = manifestWriterCount(writePoolParallelism, files.size());
    return ManifestFiles.writeParallel(
        files, groupCount, writePool(), group -> writeDeleteFileGroup(group, spec));
  }

  private List<ManifestFile> writeDeleteFileGroup(
      Collection<DeleteFile> files, PartitionSpec spec) {
    RollingManifestWriter<DeleteFile> writer = newRollingDeleteManifestWriter(spec);

    try (RollingManifestWriter<DeleteFile> closableWriter = writer) {
      for (DeleteFile file : files) {
        if (file.dataSequenceNumber() != null) {
          closableWriter.add(file, file.dataSequenceNumber());
        } else {
          closableWriter.add(file);
        }
      }
    } catch (IOException e) {
      throw new RuntimeIOException(e, "Failed to write delete manifests");
    }

    return writer.toManifestFiles();
  }

  /**
   * Calculates how many manifest writers can be used concurrently to handle the given number of
   * files without creating too small manifests.
   *
   * @param workerPoolSize the size of the available worker pool
   * @param fileCount the total number of files to be processed
   * @return the number of manifest writers that can be used concurrently
   */
  @VisibleForTesting
  static int manifestWriterCount(int workerPoolSize, int fileCount) {
    int limit = IntMath.divide(fileCount, MIN_FILE_GROUP_SIZE, RoundingMode.HALF_UP);
    return Math.max(1, Math.min(workerPoolSize, limit));
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Retry the write/commit after confirming object-store health and credentials.
  2. Verify write permissions on the table metadata location.
  3. Inspect the wrapped IOException cause for the exact storage failure.
  4. If failing intermittently under parallel writes, tune write worker pool size or merge commit batching.

Example fix

// before
DeleteFile deleteFile = ...;
table.newRowDelta().addDeletes(deleteFile).commit(); // fails: RuntimeIOException: Failed to write delete manifests
// after
// fix FileIO credentials, then with retry
Tasks.foreach(() -> table.newRowDelta().addDeletes(deleteFile).commit())
    .retry(3).exponentialBackoff(100, 4);
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm delete support and a writable metadata location before row-delta commits
ValidationException.check(base.formatVersion() >= 2, "delete files require format v2");
// plus a FileIO write probe as in error 651

Try / catch

try {
  table.newRowDelta().addDeletes(deleteFile).commit();
} catch (RuntimeIOException e) {
  // check cause for storage failure; verify object-store health, then retry
  throw new RuntimeException("commit failed writing delete manifests, check " + e.getCause(), e);
}

Prevention

When it happens

Trigger: Operations producing delete files (row-level delete via Spark MERGE/DELETE, newDelete, newRewrite with delete files) committing when FileIO cannot write the delete manifest Avro files.

Common situations: Object-store outage or throttling during a MERGE INTO job; metadata directory permissions changed; disk full; credential rotation invalidating long-running write sessions; HDFS name-node failover mid-commit.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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