apache/beam · error · RuntimeException
Failed to read delete manifest
Error message
Failed to read delete manifest: ${manifest.path()} What it means
This method reads a delete manifest and copies applicable delete files (with reduced columns for the relevant equality/delete path fields). Any exception while iterating manifest entries is wrapped in a RuntimeException naming the manifest path.
Solutions
- Open the manifest at the reported path directly to confirm it exists and is readable; inspect the wrapped cause for the real error
- Retry the scan to rule out transient object-store failures
- Ensure snapshot/manifest retention policies keep all manifests in the scanned range for the duration of the pipeline
Example fix
// before table.expireSnapshots().expireOlderThan(System.currentTimeMillis()).commit(); // deletes manifests scan still needs // after long watermark = System.currentTimeMillis() - Duration.ofHours(24).toMillis(); table.expireSnapshots().expireOlderThan(watermark).commit();
Defensive patterns
Strategy: retry
Validate before calling
checkState(table.io().newInputFile(manifest.path()).exists(),
"delete manifest missing: " + manifest.path()); Try / catch
try {
readDeleteFiles(manifest);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Failed to read delete manifest:")) {
// retry with backoff; surface e.getCause() for storage diagnostics
} else throw e;
} Prevention
- Pin manifest retention to outlast pipeline runtime
- Grant workers read access to the table metadata location
- Monitor for concurrent table-maintenance jobs
When it happens
Trigger: Reading a manifest of type DELETES during changelog task creation when the manifest is unreadable, was deleted by retention, or its entries fail to deserialize.
Common situations: Manifest files removed by expireSnapshots mid-scan; corrupted manifests; transient GCS/S3 errors; permission changes on the metadata directory.
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 collect file statuses for snapshot
- Failed to plan deleted rows tasks
- A schema is required to write non-schema'd data.
- A sink must inherit iobase.Sink, iobase.NativeSink, or be a…
- Adding required columns is not yet supported. Encountered…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/a88300ce60c75a6c.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/iceberg/src/main/java/org/apache/iceberg/BeamBaseIncrementalChangelogScan.java:761
ManifestFiles.readDeleteManifest(manifest, table().io(), table().specs())) {
for (ManifestEntry<DeleteFile> entry : reader.entries()) {
if (entry.status() == ManifestEntry.Status.DELETED
&& entry.snapshotId().equals(targetSnapshotId)) {
DeleteFile file = entry.file();
if (!partitionMatchesFilter(file)) {
continue;
}
Set<Integer> columns =
file.content() == FileContent.POSITION_DELETES
? Set.of(MetadataColumns.DELETE_FILE_PATH.fieldId())
: Set.copyOf(file.equalityFieldIds());
deleteFiles.add(ContentFileUtil.copy(file, true, columns));
}
}
} catch (Exception e) {
throw new RuntimeException("Failed to read delete manifest: " + manifest.path(), e);
}
return deleteFiles;
}
/**
* Prunes delete manifests based on partition filter to avoid processing irrelevant manifests.
* This significantly improves performance when only a subset of partitions are relevant to the
* scan.
*
* @param manifests all delete manifests to consider
* @return list of manifests that might contain relevant delete files
*/
private List<ManifestFile> pruneManifestsByPartition(List<ManifestFile> manifests) {
Expression currentFilter = filter();
// If there's no filter, return all manifests
if (currentFilter == null || currentFilter.equals(Expressions.alwaysTrue())) {View on GitHub (pinned to 12126d8942)