apache/iceberg · error · IllegalArgumentException

Cannot cache changes: FileIO is null

Error message

Cannot cache changes: FileIO is null

What it means

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.

Solutions

  1. Load manifests through a fully initialized Table (catalog.loadTable) so io() is non-null before calling dataManifests()
  2. Pass the table's FileIO explicitly via the snapshot API overloads (dataManifests(fileIO)) where available
  3. If working from TableMetadata, build the snapshot with table.io() instead of the no-IO constructor
  4. Ensure SerializableTable/serialized table state keeps a non-null FileIO supplier

Example fix

// before
Snapshot snap = table.operations().current().snapshots()[0];
List<ManifestFile> m = snap.dataManifests(null).stream()...; // no IO
// after
List<ManifestFile> m = snap.dataManifests(table.io()).stream()...;
Defensive patterns

Strategy: type-guard

Validate before calling

if (table.io() == null) throw new IllegalStateException("table FileIO not initialized; load via catalog.loadTable");

Type guard

boolean hasIO(Snapshot s, FileIO io) { return io != null && s != null; }

Try / catch

try { snapshot.dataManifests(table.io()); } catch (IllegalArgumentException e) { throw new IllegalStateException("use an IO-backed snapshot", e); }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/BaseSnapshot.java:171

  @Override
  public Long firstRowId() {
    return firstRowId;
  }

  @Override
  public Long addedRows() {
    return addedRows;
  }

  @Override
  public String keyId() {
    return keyId;
  }

  private void cacheManifests(FileIO fileIO) {
    if (fileIO == null) {
      throw new IllegalArgumentException("Cannot cache changes: FileIO is null");
    }

    if (allManifests == null && v1ManifestLocations != null) {
      // if we have a collection of manifest locations, then we need to load them here
      allManifests =
          Lists.transform(
              Arrays.asList(v1ManifestLocations),
              location ->
                  new GenericManifestFile(fileIO.newInputFile(location), 0, this.snapshotId));
    }

    if (allManifests == null) {
      // if manifests isn't set, then the snapshotFile is set and should be read to get the list
      this.allManifests =
          ManifestLists.read(
              ManifestLists.newInputFile(
                  fileIO, new BaseManifestListFile(manifestListLocation, keyId)));
    }

View on GitHub (pinned to 86d9c8fc54)