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
- Check the wrapped cause (e.getCause()) for the real storage error and fix storage connectivity/credentials
- Retry the operation — manifest copies are idempotent per snapshot attempt
- 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
- Use retry with backoff around snapshot commits for transient storage errors
- Keep cloud credentials valid for the full commit duration
- Monitor object-store error rates during commit windows
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
- Failed to write manifest
- Failed to close manifest: %s
- Failed to close manifest writer
- Failed to close current writer
- Failed to create file: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/5ac6ec55bc85995f.
Report an issue: GitHub.