apache/iceberg · error · RuntimeIOException
Cannot read manifest list file: %s
Error message
Cannot read manifest list file: %s
What it means
Thrown when reading a manifest list (snapshot list) Avro file fails with an IOException. ManifestLists.read opens the file via the table's FileIO and projects the ManifestFile schema; any I/O failure while opening or reading is wrapped in RuntimeIOException.
Source
Thrown at core/src/main/java/org/apache/iceberg/ManifestLists.java:56
return ManifestFiles.contentCache(io).tryCache(input);
}
return input;
}
static List<ManifestFile> read(InputFile manifestList) {
try (CloseableIterable<ManifestFile> files =
InternalData.read(FileFormat.AVRO, manifestList)
.setRootType(GenericManifestFile.class)
.setCustomType(
ManifestFile.PARTITION_SUMMARIES_ELEMENT_ID, GenericPartitionFieldSummary.class)
.project(ManifestFile.schema())
.build()) {
return Lists.newArrayList(files);
} catch (IOException e) {
throw new RuntimeIOException(
e, "Cannot read manifest list file: %s", manifestList.location());
}
}
static ManifestListWriter write(
int formatVersion,
OutputFile manifestListFile,
EncryptionManager encryptionManager,
long snapshotId,
Long parentSnapshotId,
long sequenceNumber,
Long firstRowId) {
switch (formatVersion) {
case 1:
Preconditions.checkArgument(
sequenceNumber == TableMetadata.INITIAL_SEQUENCE_NUMBER,
"Invalid sequence number for v1 manifest list: %s",
sequenceNumber);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check the wrapped IOException cause for file-not-found vs. access/network error.
- Verify the file still exists at the location in the snapshot metadata; if deleted by expiration, restore from backup or roll back the table.
- Confirm encryption keys and FileIO config match those used at write time.
- Retry on transient network/object-store errors.
Example fix
// before: aggressive expire before dependent readers finish expiringSnapshots.expireOlderThan(System.currentTimeMillis()); // after: retain snapshots newer than the oldest active reader table's current snapshot long safeTs = oldestDependentSnapshotTs(); expiringSnapshots.expireOlderThan(safeTs);
Defensive patterns
Strategy: try-catch
Validate before calling
// check file exists and is readable before read
InputFile in = io.newInputFile(manifestListLocation);
if (!in.exists()) { throw new IllegalStateException("manifest list missing: " + manifestListLocation); } Try / catch
try {
List<ManifestFile> files = ManifestLists.read(io, manifestListLocation);
} catch (RuntimeIOException e) {
if (causeIsNotFound(e)) handleMissingSnapshot(); // roll back / restore from backup
else retry();
} Prevention
- Don't expire snapshots while dependent readers may still reference them
- Verify retention/cleanup jobs keep files referenced by current metadata
- Match encryption config between writers and readers
- Retry transient object-store read failures
When it happens
Trigger: SnapshotProducer/operations call ManifestLists.read(...) for a parent snapshot or during cleanup; the manifest list file cannot be opened or read (missing file, network error, decryption failure).
Common situations: Metadata file references a manifest list that was deleted (e.g., orphan cleanup ran concurrently, retention too aggressive); object store connectivity failure; wrong encryption key/key management config; corrupted file.
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 create snapshot list writer for path: %s
- Failed to close manifest reader
- Failed to create manifest writer for path: %s
- Cannot read manifest list file: %s
- Failed to read manifest: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/98e890bb15e1793f.
Report an issue: GitHub.