{"record":{"id":"81d9a3fac9e3d4f9","repo":"apache/iceberg","slug":"cannot-cache-changes-fileio-is-null","errorCode":null,"errorMessage":"Cannot cache changes: FileIO is null","messagePattern":"Cannot cache changes: FileIO is null","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/BaseSnapshot.java","lineNumber":171,"sourceCode":"\n  @Override\n  public Long firstRowId() {\n    return firstRowId;\n  }\n\n  @Override\n  public Long addedRows() {\n    return addedRows;\n  }\n\n  @Override\n  public String keyId() {\n    return keyId;\n  }\n\n  private void cacheManifests(FileIO fileIO) {\n    if (fileIO == null) {\n      throw new IllegalArgumentException(\"Cannot cache changes: FileIO is null\");\n    }\n\n    if (allManifests == null && v1ManifestLocations != null) {\n      // if we have a collection of manifest locations, then we need to load them here\n      allManifests =\n          Lists.transform(\n              Arrays.asList(v1ManifestLocations),\n              location ->\n                  new GenericManifestFile(fileIO.newInputFile(location), 0, this.snapshotId));\n    }\n\n    if (allManifests == null) {\n      // if manifests isn't set, then the snapshotFile is set and should be read to get the list\n      this.allManifests =\n          ManifestLists.read(\n              ManifestLists.newInputFile(\n                  fileIO, new BaseManifestListFile(manifestListLocation, keyId)));\n    }","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/BaseSnapshot.java#L153-L189","documentation":"BaseSnapshot.cacheManifests needs a FileIO to load manifest files from their locations, but was handed a null FileIO. Snapshots obtained without an initialized table IO (e.g. from deserialization or a raw TableMetadata) cannot lazily load manifests, so an IllegalArgumentException is thrown.","triggerScenarios":"Calling snapshot.dataManifests()/deleteManifests()/allManifests() on a Snapshot that was constructed without a FileIO — e.g. a snapshot obtained from TableMetadata directly, a deserialized snapshot, or a table whose io() was never initialized (lazy table loading).","commonSituations":"Reading snapshots in a custom catalog that did not wire the FileIO; using snapshot objects recovered from serialized job state; accessing manifests from a MetadataTable or test harness that built snapshots manually.","solutions":["Load manifests through a fully initialized Table (catalog.loadTable) so io() is non-null before calling dataManifests()","Pass the table's FileIO explicitly via the snapshot API overloads (dataManifests(fileIO)) where available","If working from TableMetadata, build the snapshot with table.io() instead of the no-IO constructor","Ensure SerializableTable/serialized table state keeps a non-null FileIO supplier"],"exampleFix":"// before\nSnapshot snap = table.operations().current().snapshots()[0];\nList<ManifestFile> m = snap.dataManifests(null).stream()...; // no IO\n// after\nList<ManifestFile> m = snap.dataManifests(table.io()).stream()...;","handlingStrategy":"type-guard","validationCode":"if (table.io() == null) throw new IllegalStateException(\"table FileIO not initialized; load via catalog.loadTable\");","typeGuard":"boolean hasIO(Snapshot s, FileIO io) { return io != null && s != null; }","tryCatchPattern":"try { snapshot.dataManifests(table.io()); } catch (IllegalArgumentException e) { throw new IllegalStateException(\"use an IO-backed snapshot\", e); }","preventionTips":["Always access snapshots through a catalog-loaded Table so io() is set","Use dataManifests(fileIO) overloads with the table's IO when constructing snapshots manually","Keep FileIO in SerializableTable suppliers when shipping tables to executors"],"tags":["iceberg","fileio","null-argument"],"backgroundTag":"null-argument","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"}