{"record":{"id":"4d79f63ef5894bf8","repo":"apache/iceberg","slug":"failed-to-list-all-reachable-files","errorCode":null,"errorMessage":"Failed to list all reachable files","messagePattern":"Failed to list all reachable files","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/ReachableFileCleanup.java","lineNumber":224,"sourceCode":"                  LOG.warn(\n                      \"Failed to determine live files in manifest {}. Retrying\", item.path(), exc))\n          .run(\n              manifest -> {\n                if (filesToDelete.isEmpty()) {\n                  return;\n                }\n\n                // Remove all the live files from the candidate deletion set\n                try (CloseableIterable<String> paths =\n                    ManifestFiles.readPaths(manifest, fileIO, specsById)) {\n                  paths.forEach(filesToDelete::remove);\n                } catch (IOException e) {\n                  throw new RuntimeIOException(e, \"Failed to read manifest file: %s\", manifest);\n                }\n              });\n\n    } catch (Throwable e) {\n      LOG.warn(\"Failed to list all reachable files\", e);\n      return Sets.newHashSet();\n    }\n\n    return filesToDelete;\n  }\n}\n","sourceCodeStart":206,"sourceCodeEnd":231,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/ReachableFileCleanup.java#L206-L231","documentation":"At the end of ReachableFileCleanup.findFilesToDelete, any Throwable escaping the per-manifest Tasks blocks is caught, logged with this warning, and an empty set of files-to-delete is returned. This makes snapshot expiration fail-safe: if reachable-file enumeration cannot be completed, no files are deleted rather than risking data loss.","triggerScenarios":"Any unrecoverable exception during reachable file enumeration during expireSnapshots — RuntimeIOException from unreadable manifests/manifest lists, storage outages, or unexpected runtime errors while reading paths.","commonSituations":"Prolonged object-store outages, credentials revoked mid-job, corrupt metadata from a broken table copy, and OOM/other runtime errors on very large tables during expiration.","solutions":["Read the logged cause; fix the underlying storage/metadata problem.","Re-run expireSnapshots — the empty result means nothing was deleted, so it is safe to retry.","For very large tables, expire incrementally (expire older snapshots in batches) to reduce resource pressure.","Restore/rewrite table metadata with RewriteTablePathUtil if paths are broken."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// pre-validate all metadata readability before expiring\nSnapshotsUtil.sortedSnapshots(table).forEach(s ->\n    table.io().newInputFile(s.manifestListLocation()).exists());","typeGuard":null,"tryCatchPattern":"// the library already falls back to an empty set; treat empty filesToDelete as 'nothing expired'\nif (result.filesDeleted() == 0 && result.filesToDeleteCount() > 0) { /* investigate and retry */ }","preventionTips":["Check storage health before running expiration","Expire snapshots incrementally on very large tables","Never assume expiration deleted files; verify the returned metrics"],"tags":["expiration","cleanup","fallback","empty-result"],"backgroundTag":"empty-result-set","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}