apache/iceberg · error · RuntimeIOException
Failed to close manifest list: %s
Error message
Failed to close manifest list: %s
What it means
During expireSnapshots cleanup, ReachableFileCleanup.pruneReferencedManifests reads each snapshot's manifest list and wraps it in a CloseableIterable. If closing that iterable raises an IOException, it is rethrown as RuntimeIOException naming the manifest list location. The failure is an I/O problem on the manifest list file.
Source
Thrown at core/src/main/java/org/apache/iceberg/ReachableFileCleanup.java:136
.throwFailureWhenFinished()
.executeWith(planExecutorService)
.onFailure(
(snapshot, exc) ->
LOG.warn(
"Failed to determine manifests for snapshot {}", snapshot.snapshotId(), exc))
.run(
snapshot -> {
try (CloseableIterable<ManifestFile> manifestFiles = readManifests(snapshot)) {
for (ManifestFile manifestFile : manifestFiles) {
candidateSet.remove(manifestFile);
if (candidateSet.isEmpty()) {
return;
}
currentManifestCallback.accept(manifestFile.copy());
}
} catch (IOException e) {
throw new RuntimeIOException(
e, "Failed to close manifest list: %s", snapshot.manifestListLocation());
}
});
return candidateSet;
}
private Set<ManifestFile> readManifests(Set<Snapshot> snapshots) {
Set<ManifestFile> manifestFiles = ConcurrentHashMap.newKeySet();
Tasks.foreach(snapshots)
.retry(3)
.stopOnFailure()
.throwFailureWhenFinished()
.executeWith(planExecutorService)
.onFailure(
(snapshot, exc) ->
LOG.warn(
"Failed to determine manifests for snapshot {}", snapshot.snapshotId(), exc))View on GitHub (pinned to 86d9c8fc54)
Solutions
- Verify the manifest list files are readable and the storage backend is healthy, then retry expireSnapshots
- Check FileIO credentials/permissions and network stability to the object store
- If files were externally deleted, restore consistency (e.g. re-register the table or repair metadata) before cleanup
Example fix
// before
expireSnapshots(table).cleanExpiredFiles(true).execute();
// after
try {
expireSnapshots(table).cleanExpiredFiles(true).execute();
} catch (RuntimeIOException e) {
LOG.error("Manifest list I/O failure during cleanup: {}", e.getMessage());
// check storage health/credentials, then retry
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify the manifest list is readable before expiration io.newInputFile(snapshot.manifestListLocation()).exists();
Try / catch
try {
expireSnapshots(table).cleanExpiredFiles(true).execute();
} catch (RuntimeIOException e) {
// inspect e.getMessage() for the manifest list location; check storage health, then retry
} Prevention
- Ensure stable connectivity to the object store before long expiration jobs
- Avoid external lifecycle rules deleting metadata objects
- Validate FileIO credentials and permissions pre-run
- Retry transient object-store failures with backoff
When it happens
Trigger: expireSnapshots with file cleanup where closing the manifest-list reader of a snapshot throws IOException — typically underlying FileIO errors such as unavailable storage, network failure, or corrupted/unreadable manifest list object.
Common situations: Object-store throttling or connectivity drops during snapshot expiration; missing/corrupted manifest list files (deleted externally or failed prior write); credential/permission problems on the warehouse path.
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 read manifest file: %s
- cleanExpiredMetadata is not supported
- RuntimeIOException
- Failed to close manifest reader
- Failed to close entries while caching changes
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f01f40ae861aff51.
Report an issue: GitHub.