apache/iceberg · error · java.lang.IllegalArgumentException
Cannot use non-v1 table
Error message
Cannot use non-v1 table '%s' as a source
What it means
Spark table migration/copy actions (e.g. SNAPSHOTTABLE/MIGRATE) load the source table via a Spark catalog and cast it to V1Table. If the loaded table implementation is not a V1Table (e.g. a V2 catalog table), the ClassCastException is caught and rethrown as this IllegalArgumentException. Only Spark's legacy v1 session-catalog tables can be used as a migration source.
Solutions
- Use the default session catalog (spark_catalog) for the source table, migrating from Hive/Parquet/CSV sources
- Verify which catalog the identifier resolves to; qualify it explicitly (e.g. spark_catalog.db.tbl)
- If the source is already Iceberg, use a different workflow (e.g. registerTable or catalog migration) instead of migrate/snapshot
Example fix
// before
CALL iceberg.system.migrate('my_catalog.my_db.my_table')
// after
CALL iceberg.system.migrate('my_db.my_hive_table') -- resolved via spark_catalog (V1Table) Defensive patterns
Strategy: validation
Validate before calling
// Verify the source resolves to a V1Table before running the procedure
var catalog = spark.sessionState().catalogManager().catalog("spark_catalog");
var table = catalog.loadTable(Identifier.of(new String[]{"db"}, "tbl"));
if (!(table instanceof org.apache.spark.sql.execution.datasources.v2.V1Table)) {
throw new IllegalStateException("Source is not a V1 (session catalog) table");
} Type guard
function isV1Source(table) { return table instanceof org.apache.spark.sql.execution.datasources.v2.V1Table; } Prevention
- Only run MIGRATE/SNAPSHOT against tables resolved via spark_catalog (Hive/Parquet/CSV sources)
- Qualify identifiers with the catalog name and confirm which catalog they resolve to
- For already-Iceberg sources, use catalog registration workflows instead of migrate
When it happens
Trigger: Calling a BaseTableCreationSparkAction subclass (MigrateTableProcedures/SnapshotTableProcedures) with a source table resolved by a catalog whose loadTable returns a Spark V2 Table implementation rather than org.apache.spark.sql.execution.datasources.v2.V1Table.
Common situations: Pointing the procedure at a table in an Iceberg or other V2 catalog instead of the built-in spark_catalog; the table identifier resolves through spark.sql.catalog.<name> whose table class is not V1Table.
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
- Altering a view is not supported by catalog:
- 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/e66820914c684700.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/BaseTableCreationSparkAction.java:83
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)