apache/iceberg · error · UncheckedIOException
Failed to close changelog scan: ${scan}
Error message
Failed to close changelog scan: ${scan} What it means
taskGroups() plans changelog tasks via scan.planTasks() inside try-with-resources; if closing the resulting CloseableIterable throws IOException, the planning failure is wrapped as UncheckedIOException with the scan description. The scan itself failed to plan/close cleanly, usually an underlying FileIO error.
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/SparkChangelogScan.java:122
@Override
public Batch toBatch() {
return new SparkBatch(
sparkContext,
table,
null != scan ? scan.fileIO() : table::io,
readConf,
EMPTY_GROUPING_KEY_TYPE,
taskGroups(),
expectedSchema,
hashCode());
}
private List<ScanTaskGroup<ChangelogScanTask>> taskGroups() {
if (taskGroups == null) {
try (CloseableIterable<ScanTaskGroup<ChangelogScanTask>> groups = scan.planTasks()) {
this.taskGroups = Lists.newArrayList(groups);
} catch (IOException e) {
throw new UncheckedIOException("Failed to close changelog scan: " + scan, e);
}
}
return taskGroups;
}
@Override
public String description() {
return String.format(
Locale.ROOT,
"%s [fromSnapshotId=%d, toSnapshotId=%d, filters=%s]",
table,
startSnapshotId,
endSnapshotId,
Spark3Util.describe(filters));
}
@OverrideView on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the cause chain for the underlying FileIO/filesystem error and fix that (missing file, credentials, network).
- Verify all referenced manifests/snapshots exist and the table metadata is consistent (run validate/expire checks).
- Retry the scan; if transient cloud-storage errors recur, add retries or check endpoint/credentials.
Defensive patterns
Strategy: try-catch
Validate before calling
// before streaming: verify table metadata is readable TableMetadataParser.read(io, metadataLoc); // throws if metadata/manifests unreadable
Try / catch
try { ... } catch (UncheckedIOException e) { log.error("changelog plan failed: {}", e.getCause()); throw e; } Prevention
- Keep manifest/metadata files intact; avoid expiring snapshots concurrently with changelog reads
- Ensure storage credentials/permissions for the table location
- Add retry with backoff for transient cloud storage errors
When it happens
Trigger: Calling tasks()/taskGroups() on SparkChangelogScan when planTasks() or the closing of the planned task iterable throws IOException (e.g. missing manifest files, filesystem outage).
Common situations: Corrupt or deleted manifest/metadata files, S3/HDFS transient errors, or snapshot expiry racing a changelog scan in Spark structured streaming.
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 scan: ${scan}
- Failed to close changelog scan: + scan
- Failed to close scan: + scan
- Failed to close changelog scan: ${scan}
- Failed to close scan: ${scan}
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/2098b60b492314da.
Report an issue: GitHub.