apache/iceberg · error · RuntimeIOException
RuntimeIOException
Error message
RuntimeIOException
What it means
During BaseRewriteManifests.apply(), entries are appended to new manifest writers on worker threads. Any underlying IOException while writing a manifest is wrapped in RuntimeIOException, which aborts the rewrite with this unchecked exception.
Source
Thrown at core/src/main/java/org/apache/iceberg/BaseRewriteManifests.java:269
manifest -> {
if (containsDeletes(manifest) || !matchesPredicate(manifest)) {
keptManifests.add(manifest);
} else {
rewrittenManifests.add(manifest);
try (ManifestReader<DataFile> reader =
ManifestFiles.read(manifest, ops().io(), ops().current().specsById())
.select(Collections.singletonList("*"))) {
reader
.liveEntries()
.forEach(
entry ->
appendEntry(
entry,
clusterByFunc.apply(entry.file()),
manifest.partitionSpecId()));
} catch (IOException x) {
throw new RuntimeIOException(x);
}
}
});
} finally {
Tasks.foreach(writers.values()).executeWith(workerPool()).run(WriterWrapper::close);
}
}
private boolean containsDeletes(ManifestFile manifest) {
return manifest.content() == ManifestContent.DELETES;
}
private boolean matchesPredicate(ManifestFile manifest) {
return predicate == null || predicate.test(manifest);
}
private void validateDeletedManifests(
Set<ManifestFile> currentManifests, long currentSnapshotID) {View on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the cause (getCause()) to find the real IOException and fix storage access (permissions, quota, connectivity).
- Retry the rewriteManifests() operation once storage is healthy — the operation is safe to rerun.
- Verify the FileIO's warehouse/metadata location is writable and has free space.
- Reduce rewrite concurrency (smaller worker pool) if object storage is throttling requests.
Example fix
// handling
try {
table.rewriteManifests().clusterBy(f -> f.partition()).commit();
} catch (RuntimeIOException e) {
LOG.error("Manifest rewrite failed: {}", e.getCause(), e);
// fix storage issue, then retry
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check the metadata location is writable
boolean writable = table.io() instanceof SupportsBulkOperations
? canWrite(table.io(), table.location() + "/metadata")
: true; Try / catch
try {
table.rewriteManifests().clusterBy(f -> f.partition()).commit();
} catch (RuntimeIOException e) {
LOG.error("Manifest write failed: {}", e.getCause(), e);
// remediate storage (space/permissions/connectivity) and retry
} Prevention
- Monitor disk/object-store capacity before large rewrites
- Verify metadata-directory write permissions for the job's service account
- Handle object-storage throttling by limiting worker pool size
- Inspect getCause() of RuntimeIOException to find the root IOException
When it happens
Trigger: An IOException occurs while writing new manifest files during a rewriteManifests() commit — disk full, permission denied, transient metadata-IO failure on the FileIO backend, or a broken connection to object storage.
Common situations: HDFS/S3 outages or throttling during large manifest rewrites; insufficient permissions on the metadata directory; disk-quota exhaustion on the warehouse volume.
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 list partitions of table %s
- Replaced and created manifests must have the same number of
- Failed to close manifest reader
- Failed to close entries while caching changes
- Failed to read manifest file: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/aaa857b143e07459.
Report an issue: GitHub.