apache/iceberg · error · RuntimeIOException
Failed to close manifest list: %s
Error message
Failed to close manifest list: %s
What it means
During expire/cleanup, IncrementalFileCleanup reads each snapshot's manifest list as a CloseableIterable; if closing that iterable raises an IOException (e.g. object-store I/O error while closing the reader), it is wrapped as RuntimeIOException with the snapshot's manifest list location. This is an I/O failure during resource cleanup while determining which files to delete.
Source
Thrown at core/src/main/java/org/apache/iceberg/IncrementalFileCleanup.java:157
// whether the snapshot that created the manifest was an ancestor of the table
// state
boolean isFromAncestor = ancestorIds.contains(snapshotId);
// whether the changes in this snapshot have been picked into the current table
// state
boolean isPicked = pickedAncestorSnapshotIds.contains(snapshotId);
// if the snapshot that wrote this manifest is no longer valid (has expired),
// then delete its deleted files. note that this is only for expired snapshots
// that are in the
// current table state
if (!fromValidSnapshots
&& (isFromAncestor || isPicked)
&& manifest.hasDeletedFiles()) {
manifestsToScan.add(manifest.copy());
}
}
} catch (IOException e) {
throw new RuntimeIOException(
e, "Failed to close manifest list: %s", snapshot.manifestListLocation());
}
});
// find manifests to clean up that were only referenced by snapshots that have expired
Set<String> manifestListsToDelete = ConcurrentHashMap.newKeySet();
Set<String> manifestsToDelete = ConcurrentHashMap.newKeySet();
Set<ManifestFile> manifestsToRevert = ConcurrentHashMap.newKeySet();
Tasks.foreach(beforeExpiration.snapshots())
.retry(3)
.suppressFailureWhenFinished()
.executeWith(planExecutorService)
.onFailure(
(snapshot, exc) ->
LOG.warn(
"Failed on snapshot {} while reading manifest list: {}",
snapshot.snapshotId(),
snapshot.manifestListLocation(),View on GitHub (pinned to 86d9c8fc54)
Solutions
- Retry the expiry job; the failure is typically transient storage I/O.
- Verify FileIO credentials and connectivity to the manifest list location shown in the message.
- Check the underlying storage service health (S3/GCS/HDFS NameNode) for errors during the job window.
- If persistent, inspect the cause chain (RuntimeIOException.getCause) for the concrete IOException.
Example fix
// before
table.expireSnapshots().olderThan(ts).execute(); // aborts on one bad close
// after
try {
table.expireSnapshots().olderThan(ts).execute();
} catch (RuntimeIOException e) {
LOG.warn("retrying expiry after I/O failure", e);
table.expireSnapshots().olderThan(ts).execute(); // transient manifest-list close failure
} Defensive patterns
Strategy: retry
Try / catch
try {
table.expireSnapshots().olderThan(ts).execute();
} catch (RuntimeIOException e) {
if (e.getCause() instanceof IOException) {
// transient manifest-list close failure; retry with backoff
retryWithBackoff(() -> table.expireSnapshots().olderThan(ts).execute());
} else {
throw e;
}
} Prevention
- Ensure stable credentials and network for FileIO storage before long expiry jobs.
- Serialize expiry jobs so they don't race each other on manifest lists.
- Monitor object-store error rates during maintenance windows.
When it happens
Trigger: Running table.expireSnapshots() (or removeOrphanFiles-style cleanup paths using IncrementalFileCleanup.cleanFiles) where closing a snapshot's manifest-list reader throws IOException - typically S3/GCS/HDFS transient I/O errors or connection resets.
Common situations: Expired credentials or network hiccups against object storage during expiry; underlying filesystem unavailable; read-ahead streams closed abnormally on the storage layer.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Failed to determine manifests for snapshot {}
- Cannot read manifest list file: %s
- Failed to read manifest file: %s
- An error occurred while aborting the stream
- Bulk deletion failed
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e6432acc2fd00d86.
Report an issue: GitHub.