apache/iceberg · error · RuntimeIOException

Failed to close manifest: %s

Error message

Failed to close manifest: %s

What it means

copyAppendManifest copies an existing manifest into a new output file and must close the manifest writer to flush AVRO data. If closing the writer's output stream raises IOException, it is wrapped in this RuntimeIOException naming the source manifest location. The copy itself failed at finalization, so the new manifest is not usable.

Source

Thrown at core/src/main/java/org/apache/iceberg/ManifestFiles.java:451

      EncryptedOutputFile outputFile,
      long snapshotId,
      SnapshotSummary.Builder summaryBuilder) {
    // use metadata that will add the current snapshot's ID for the rewrite
    // read first_row_id as null because this copies the incoming manifest before commit
    InheritableMetadata inheritableMetadata = InheritableMetadataFactory.forCopy(snapshotId);
    try (ManifestReader<DataFile> reader =
        new ManifestReader<>(
            toCopy, specId, specsById, inheritableMetadata, null, FileType.DATA_FILES)) {
      return copyManifestInternal(
          formatVersion,
          null, // do not produce row IDs
          reader,
          outputFile,
          snapshotId,
          summaryBuilder,
          ManifestEntry.Status.ADDED);
    } catch (IOException e) {
      throw new RuntimeIOException(e, "Failed to close manifest: %s", toCopy.location());
    }
  }

  static ManifestFile copyRewriteManifest(
      int formatVersion,
      int specId,
      Long firstRowId,
      InputFile toCopy,
      Map<Integer, PartitionSpec> specsById,
      EncryptedOutputFile outputFile,
      long snapshotId,
      SnapshotSummary.Builder summaryBuilder) {
    // for a rewritten manifest all snapshot ids should be set. use empty metadata to throw an
    // exception if it is not
    InheritableMetadata inheritableMetadata = InheritableMetadataFactory.empty();
    try (ManifestReader<DataFile> reader =
        new ManifestReader<>(
            toCopy, specId, specsById, inheritableMetadata, firstRowId, FileType.DATA_FILES)) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check the wrapped cause (e.getCause()) for the real storage error and fix storage connectivity/credentials
  2. Retry the operation — manifest copies are idempotent per snapshot attempt
  3. Verify sufficient disk/quota at the manifest output location
Defensive patterns

Strategy: retry

Validate before calling

// verify output location is writable before copying
io.newInputFile(toCopy.location()).exists(); // source readable check
FileIO finalIo = io; // ensure credentials are fresh for the duration

Try / catch

try {
  ManifestFile copied = ManifestFiles.copyAppendManifest(fv, specId, toCopy, io, outputFile, snapshotId, summaryBuilder);
} catch (RuntimeIOException e) {
  // inspect e.getCause(); transient storage errors are safe to retry
  throw e;
}

Prevention

When it happens

Trigger: Calling ManifestFiles.copyAppendManifest(...) during snapshot commit when the underlying OutputFile cannot be flushed/closed — e.g. storage backend failure, credentials expired mid-write, or network interruption to object storage.

Common situations: S3/GCS/HDFS transient failures during commit; expired cloud credentials; quota or rate limits on the object store; local disk full when writing to a file: location.

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/5ac6ec55bc85995f. Report an issue: GitHub.