apache/iceberg · error · IllegalArgumentException

Cannot use non-v1 table

Error message

Cannot use non-v1 table '%s' as a source

What it means

The action casts the loaded source table to Spark's V1Table; if the catalog returns a different CatalogTable implementation (V2 or non-v1), ClassCastException is caught and rethrown as IllegalArgumentException 'Cannot use non-v1 table'. The action only supports V1 table sources.

Solutions

  1. Source the table from a catalog that exposes V1Table (e.g. default spark_catalog for Hive/Parquet sources)
  2. Use a different action appropriate for Iceberg-to-Iceberg copies (e.g. snapshot against an Iceberg table is unnecessary — register the table instead)
  3. Check which catalog plugin the source identifier resolves through

Example fix

// before
CALL spark_catalog.system.migrate('iceberg_db.tbl') // source is v2
// after
CALL spark_catalog.system.migrate('parquet_db.tbl') // source is a v1/Hive table
Defensive patterns

Strategy: type-guard

Validate before calling

CatalogPlugin cat = ...; Table loaded = cat.loadTable(ident); // confirm it maps to V1Table before invoking the action

Type guard

boolean isV1Source(CatalogTable t) { return t instanceof V1Table; }

Try / catch

try { callAction(...); } catch (IllegalArgumentException e) { if (e.getMessage().contains("non-v1 table")) { /* choose different source catalog */ } throw e; }

Prevention

When it happens

Trigger: snapshot/migrate-style actions where the source resolves through a catalog that returns a V2Table (e.g. Spark's built-in v2 catalog, JDBC v2, or another Iceberg catalog plugin) rather than V1Table.

Common situations: Migrating from a table in the Iceberg spark catalog itself (already Iceberg → returns v2); using spark_catalog with a session catalog that doesn't expose V1Table; mixing catalog plugins.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/actions/BaseTableCreationSparkAction.java:82

  private final Identifier sourceTableIdent;

  // Optional Parameters for destination
  private final Map<String, String> additionalProperties = Maps.newHashMap();

  BaseTableCreationSparkAction(
      SparkSession spark, CatalogPlugin sourceCatalog, Identifier sourceTableIdent) {
    super(spark);

    this.sourceCatalog = checkSourceCatalog(sourceCatalog);
    this.sourceTableIdent = sourceTableIdent;

    try {
      this.sourceTable = (V1Table) this.sourceCatalog.loadTable(sourceTableIdent);
      this.sourceCatalogTable = sourceTable.v1Table();
    } catch (org.apache.spark.sql.catalyst.analysis.NoSuchTableException e) {
      throw new NoSuchTableException("Cannot find source table '%s'", sourceTableIdent);
    } catch (ClassCastException e) {
      throw new IllegalArgumentException(
          String.format("Cannot use non-v1 table '%s' as a source", sourceTableIdent), e);
    }
    validateSourceTable();

    this.sourceTableLocation =
        CatalogUtils.URIToString(sourceCatalogTable.storage().locationUri().get());
  }

  protected abstract TableCatalog checkSourceCatalog(CatalogPlugin catalog);

  protected abstract StagingTableCatalog destCatalog();

  protected abstract Identifier destTableIdent();

  protected abstract Map<String, String> destTableProps();

  protected String sourceTableLocation() {
    return sourceTableLocation;

View on GitHub (pinned to 86d9c8fc54)