{"record":{"id":"67dfe41048c4c8c7","repo":"apache/iceberg","slug":"failed-to-read-manifest-file-s","errorCode":null,"errorMessage":"Failed to read manifest file: %s","messagePattern":"Failed to read manifest file: (.+?)","errorType":"exception","errorClass":"RuntimeIOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/CatalogUtil.java","lineNumber":196,"sourceCode":"                LOG.warn(\"Failed to get deleted files: this may cause orphaned data files\", exc))\n        .run(\n            manifest -> {\n              try (ManifestReader<?> reader = ManifestFiles.open(manifest, io, specsById)) {\n                List<String> pathsToDelete = Lists.newArrayList();\n                for (ManifestEntry<?> entry : reader.entries()) {\n                  // intern the file path because the weak key map uses identity (==) instead of\n                  // equals\n                  String path = entry.file().location().intern();\n                  Boolean alreadyDeleted = deletedFiles.putIfAbsent(path, true);\n                  if (alreadyDeleted == null || !alreadyDeleted) {\n                    pathsToDelete.add(path);\n                  }\n                }\n\n                String type = reader.isDeleteManifestReader() ? \"delete\" : \"data\";\n                deleteFiles(io, pathsToDelete, type, false);\n              } catch (IOException e) {\n                throw new RuntimeIOException(\n                    e, \"Failed to read manifest file: %s\", manifest.path());\n              }\n            });\n  }\n\n  /**\n   * Helper to delete files. Bulk deletion is used if possible, otherwise deletions are done\n   * concurrently for non-bulk FileIO.\n   *\n   * @param io FileIO for deletes\n   * @param files files to delete\n   * @param type type of files being deleted\n   */\n  public static void deleteFiles(FileIO io, Iterable<String> files, String type) {\n    deleteFiles(io, files, type, true);\n  }\n\n  /**","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/CatalogUtil.java#L178-L214","documentation":"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.","triggerScenarios":"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.","commonSituations":"Manifests removed manually or by an external lifecycle policy; expired S3/GCS/ADLS credentials mid-operation; network partitions to object storage.","solutions":["Verify the manifest file exists and is readable via the table's FileIO (check credentials and permissions)","Re-run the operation after fixing transient storage/credential issues","Ensure no external process deletes metadata files concurrently","Restore the corrupted manifest from backup if available"],"exampleFix":"// before\ntable.expireSnapshots().expireOlderThan(ts).commit(); // may throw on unreadable manifest\n// after\ntry {\n  table.expireSnapshots().expireOlderThan(ts).commit();\n} catch (RuntimeIOException e) {\n  logger.error(\"Manifest unreadable during expiration: {}\", e.getMessage(), e);\n  // fix storage access, then retry\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (RuntimeIOException e) { if (e.getCause() instanceof IOException) { /* check credentials/connectivity for the manifest path */ } throw e; }","preventionTips":["Never manually delete files under the table's metadata directory","Ensure FileIO credentials are valid and long-lived enough for the whole expiration","Avoid concurrent metadata cleanup by multiple jobs","Test expiration against a copy of production metadata before running at scale"],"tags":["io","manifest","storage"],"backgroundTag":"file-read-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}