apache/iceberg · error · RuntimeIOException
Failed to close entries while caching changes
Error message
Failed to close entries while caching changes
What it means
A sibling of the reader-close failure on the data path: while caching data-file changes, closing the ManifestReader after iteration throws an IOException, which Iceberg converts to RuntimeIOException with message "Failed to close entries while caching changes".
Source
Thrown at core/src/main/java/org/apache/iceberg/BaseSnapshot.java:324
Iterables.filter(
dataManifests(fileIO), manifest -> Objects.equal(manifest.snapshotId(), snapshotId));
try (CloseableIterable<ManifestEntry<DataFile>> entries =
new ManifestGroup(fileIO, changedManifests).ignoreExisting().entries()) {
for (ManifestEntry<DataFile> entry : entries) {
switch (entry.status()) {
case ADDED:
adds.add(entry.file().copy());
break;
case DELETED:
deletes.add(entry.file().copyWithoutStats());
break;
default:
throw new IllegalStateException(
"Unexpected entry status, not added or deleted: " + entry);
}
}
} catch (IOException e) {
throw new RuntimeIOException(e, "Failed to close entries while caching changes");
}
this.addedDataFiles = adds.build();
this.removedDataFiles = deletes.build();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof BaseSnapshot) {
BaseSnapshot other = (BaseSnapshot) o;
return this.snapshotId == other.snapshotId()
&& Objects.equal(this.parentId, other.parentId())
&& this.sequenceNumber == other.sequenceNumber()
&& this.timestampMillis == other.timestampMillis()View on GitHub (pinned to 86d9c8fc54)
Solutions
- Retry the call after table.refresh(); typically transient
- Ensure credentials/Tokens are valid for the duration of the scan (refresh STS tokens, session tokens)
- Prevent expireSnapshots/orphan cleanup from racing with incremental change readers
- Check storage backend health and network stability
Example fix
// before
List<DataFile> added = snapshot.addedDataFiles();
// after
try {
List<DataFile> added = snapshot.addedDataFiles();
} catch (RuntimeIOException e) {
table.refresh();
List<DataFile> added = snapshot.addedDataFiles();
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure credentials valid for scan duration if (credentialsExpiryEpochMs < System.currentTimeMillis() + scanDurationMs) refreshCredentials();
Try / catch
try { snapshot.addedDataFiles(); } catch (RuntimeIOException e) { table.refresh(); retryWithBackoff(); } Prevention
- Use long-lived or auto-refreshing credentials for long incremental scans
- Configure FileIO retry/throttle settings for the cloud backend
- Exclude cleanup jobs from running concurrently with change caching
When it happens
Trigger: Calling addedDataFiles()/removedDataFiles() when the underlying object store fails while closing the manifest reader: connection reset, credentials expiring mid-scan, or the manifest being deleted concurrently.
Common situations: Long-running incremental-scan jobs whose cloud credentials expire; S3/GCS throttling; cleanup jobs removing manifests mid-read.
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 reader
- Failed to close current writer
- RuntimeIOException
- Failed to close manifest list: %s
- Failed to read manifest file: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/010d9fd711ac5b34.
Report an issue: GitHub.