apache/iceberg · error · java.lang.IllegalArgumentException

Unknown Spark table type: %s

Error message

Unknown Spark table type: %s

What it means

SparkCatalog.loadTable(ident, version) handles a closed set of SparkTable subtypes (regular SparkTable, SparkChangelogTable). If the loaded table object is neither, the method throws IllegalArgumentException 'Unknown Spark table type: <class name>'. This indicates the table implementation was swapped by an extension or wrapper the catalog does not recognize.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:214

      } catch (NumberFormatException e) {
        SnapshotRef ref = sparkTable.table().refs().get(version);
        ValidationException.check(
            ref != null,
            "Cannot find matching snapshot ID or reference name for version %s",
            version);

        if (ref.isBranch()) {
          return sparkTable.copyWithBranch(version);
        } else {
          return sparkTable.copyWithSnapshotId(ref.snapshotId());
        }
      }

    } else if (table instanceof SparkChangelogTable) {
      throw new UnsupportedOperationException("AS OF is not supported for changelogs");

    } else {
      throw new IllegalArgumentException("Unknown Spark table type: " + table.getClass().getName());
    }
  }

  @Override
  public Table loadTable(Identifier ident, long timestamp) throws NoSuchTableException {
    Table table = loadTable(ident);

    if (table instanceof SparkTable) {
      SparkTable sparkTable = (SparkTable) table;

      Preconditions.checkArgument(
          sparkTable.snapshotId() == null && sparkTable.branch() == null,
          "Cannot do time-travel based on both table identifier and AS OF");

      // convert the timestamp to milliseconds as Spark passes microseconds
      // but Iceberg uses milliseconds for snapshot timestamps
      long timestampMillis = TimeUnit.MICROSECONDS.toMillis(timestamp);
      long snapshotId = SnapshotUtil.snapshotIdAsOfTime(sparkTable.table(), timestampMillis);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure the catalog returns vanilla org.apache.iceberg.spark.SparkTable for time-travel loads; unwrap or register support for the custom type.
  2. Align Iceberg jar versions across the cluster (no mixed iceberg-spark-runtime versions on the classpath).
  3. Update the Iceberg extension/plugin to a version compatible with this SparkCatalog implementation.
  4. As a workaround, do time travel via DataFrame reader options (snapshot-id / as-of-timestamp) instead of the versioned loadTable API.

Example fix

// before
Table t = sparkCatalog.loadTable(ident, version); // custom wrapper type -> IllegalArgumentException

// after
Dataset<Row> df = spark.read().format("iceberg")
    .option("snapshot-id", version)
    .load("db.tbl"); // bypasses type dispatch
Defensive patterns

Strategy: try-catch

Validate before calling

Table t = sparkCatalog.loadTable(ident);
boolean supported = t instanceof org.apache.iceberg.spark.SparkTable
    || t instanceof org.apache.iceberg.spark.SparkChangelogTable;
if (!supported) {
  throw new IllegalStateException("Unsupported table implementation for time travel: " + t.getClass().getName());
}

Type guard

boolean isVersionedLoadSupported = t instanceof org.apache.iceberg.spark.SparkTable;

Try / catch

try {
  return sparkCatalog.loadTable(ident, version);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Unknown Spark table type")) { /* fall back to snapshot-id read option */ }
  throw e;
}

Prevention

When it happens

Trigger: loadTable(ident, version) where the resolved Table is a custom/extension subclass of SparkTable (e.g. from a third-party catalog plugin or instrumentation wrapper) that is not SparkTable or SparkChangelogTable.

Common situations: Using Iceberg extensions or vendor plugins that wrap SparkTable; classpath mixing of different Iceberg versions producing unexpected table classes; custom catalog returning its own Table implementation through a path that reaches SparkCatalog's time-travel loader.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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