apache/iceberg · error · RuntimeIOException
Failed to close manifest entries: %s
Error message
Failed to close manifest entries: %s
What it means
manifestHasDeletedFiles scans manifest entries to decide whether the manifest may contain files matching a delete expression. If the CloseableIterable of entries throws IOException while being consumed or closed, it is wrapped in this RuntimeIOException naming the manifest. The scan planning for the delete operation aborts.
Source
Thrown at core/src/main/java/org/apache/iceberg/ManifestFilterManager.java:492
ValidationException.check(
allRowsMatch || isDelete, // ignore delete files where some records may not match the
// expression
"Cannot delete file where some, but not all, rows match filter %s: %s",
this.deleteExpression,
file.location());
if (allRowsMatch) {
if (failAnyDelete) {
throw new DeleteException(reader.spec().partitionToPath(file.partition()));
}
// as soon as a deleted file is detected, stop scanning
return true;
}
}
}
} catch (IOException e) {
throw new RuntimeIOException(e, "Failed to close manifest entries: %s", manifest);
}
return false;
}
private boolean isDanglingDV(DeleteFile file) {
return ContentFileUtil.isDV(file) && removedDataFilePaths.contains(file.referencedDataFile());
}
@SuppressWarnings({"CollectionUndefinedEquality", "checkstyle:CyclomaticComplexity"})
private ManifestFile filterManifestWithDeletedFiles(
PartitionAndMetricsEvaluator evaluator, ManifestFile manifest, ManifestReader<F> reader) {
boolean isDelete = reader.isDeleteManifestReader();
// when this point is reached, there is at least one file that will be deleted in the
// manifest. produce a copy of the manifest with all deleted files removed.
Set<F> deletedFiles = newFileSet();
AtomicInteger duplicateDeleteCount = new AtomicInteger(0);
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Verify the manifest file exists and is readable at its location
- Restore the manifest if it was deleted by external cleanup processes
- Check the wrapped cause for the precise storage error and fix permissions/connectivity
Defensive patterns
Strategy: try-catch
Validate before calling
if (!io.newInputFile(manifest.location()).exists()) {
throw new IllegalStateException("Manifest missing before filter: " + manifest.location());
} Try / catch
try {
boolean hasDeletes = manifestHasDeletedFiles(manifest, ...);
} catch (RuntimeIOException e) {
throw new IllegalStateException("Cannot read manifest entries: " + manifest.location() + "; check storage/permissions", e);
} Prevention
- Prevent external lifecycle policies from deleting active manifests
- Validate manifest readability during planning, not just at commit
- Monitor for missing-object errors on the warehouse bucket
When it happens
Trigger: Calling filterManifest (via MergingSnapshotProducer) on a manifest whose entries cannot be read — corrupt manifest data file, missing manifest object in storage, or IO error while streaming entries.
Common situations: Manifests deleted externally (e.g. manual cleanup or aggressive lifecycle rules) before commit; corrupt AVRO manifests; storage read errors mid-scan; permission changes removing read access to old manifests.
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 close manifest: %s
- Failed to close manifest writer
- Failed to create file: %s
- Failed to delete: %s
- Failed to close encryption manager
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/348e04c95efbba15.
Report an issue: GitHub.