apache/iceberg · error · RuntimeIOException

Failed to read manifest file: %s

Error message

Failed to read manifest file: %s

What it means

During expiration of table data (dropTableData / deleteRemovedMetadataFiles), Iceberg reads each manifest to determine which files are deletable; if an IOException occurs while reading, it is wrapped in RuntimeIOException with the manifest path. Delete operations abort rather than silently skipping, since skipping could orphan or wrongly retain/delete data files.

Source

Thrown at core/src/main/java/org/apache/iceberg/CatalogUtil.java:196

                LOG.warn("Failed to get deleted files: this may cause orphaned data files", exc))
        .run(
            manifest -> {
              try (ManifestReader<?> reader = ManifestFiles.open(manifest, io, specsById)) {
                List<String> pathsToDelete = Lists.newArrayList();
                for (ManifestEntry<?> entry : reader.entries()) {
                  // intern the file path because the weak key map uses identity (==) instead of
                  // equals
                  String path = entry.file().location().intern();
                  Boolean alreadyDeleted = deletedFiles.putIfAbsent(path, true);
                  if (alreadyDeleted == null || !alreadyDeleted) {
                    pathsToDelete.add(path);
                  }
                }

                String type = reader.isDeleteManifestReader() ? "delete" : "data";
                deleteFiles(io, pathsToDelete, type, false);
              } catch (IOException e) {
                throw new RuntimeIOException(
                    e, "Failed to read manifest file: %s", manifest.path());
              }
            });
  }

  /**
   * Helper to delete files. Bulk deletion is used if possible, otherwise deletions are done
   * concurrently for non-bulk FileIO.
   *
   * @param io FileIO for deletes
   * @param files files to delete
   * @param type type of files being deleted
   */
  public static void deleteFiles(FileIO io, Iterable<String> files, String type) {
    deleteFiles(io, files, type, true);
  }

  /**

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the manifest file exists and is readable via the table's FileIO (check credentials and permissions)
  2. Re-run the operation after fixing transient storage/credential issues
  3. Ensure no external process deletes metadata files concurrently
  4. Restore the corrupted manifest from backup if available

Example fix

// before
table.expireSnapshots().expireOlderThan(ts).commit(); // may throw on unreadable manifest
// after
try {
  table.expireSnapshots().expireOlderThan(ts).commit();
} catch (RuntimeIOException e) {
  logger.error("Manifest unreadable during expiration: {}", e.getMessage(), e);
  // fix storage access, then retry
}
Defensive patterns

Strategy: try-catch

Try / catch

catch (RuntimeIOException e) { if (e.getCause() instanceof IOException) { /* check credentials/connectivity for the manifest path */ } throw e; }

Prevention

When it happens

Trigger: Calling Table.expireSnapshots()...expireOlderThan(ts).commit() or catalog.dropTableData(ident) when a manifest listed in a snapshot cannot be read — file deleted/corrupted in storage, credentials/permission problems, transient storage errors.

Common situations: Manifests removed manually or by an external lifecycle policy; expired S3/GCS/ADLS credentials mid-operation; network partitions to object storage.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/67dfe41048c4c8c7. Report an issue: GitHub.