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
- Source the table from a catalog that exposes V1Table (e.g. default spark_catalog for Hive/Parquet sources)
- Use a different action appropriate for Iceberg-to-Iceberg copies (e.g. snapshot against an Iceberg table is unnecessary — register the table instead)
- 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
- Source migrate/snapshot actions from Hive/parquet tables via spark_catalog (V1)
- Do not migrate tables already managed by Iceberg — register instead
- Check which CatalogPlugin implementation resolves the source identifier
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
- Cannot use catalog ( ): not a TableCatalog
- Cannot use catalog ( ): not a TableCatalog
- Altering a view is not supported by catalog:
- Altering a view is not supported by catalog
- Altering a view is not supported by catalog
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)