{"record":{"id":"e66820914c684700","repo":"apache/iceberg","slug":"cannot-use-non-v1-table-s-as-a-source-e66820","errorCode":null,"errorMessage":"Cannot use non-v1 table '%s' as a source","messagePattern":"Cannot use non-v1 table '(.+?)' as a source","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/BaseTableCreationSparkAction.java","lineNumber":83,"sourceCode":"  private final Identifier sourceTableIdent;\n\n  // Optional Parameters for destination\n  private final Map<String, String> additionalProperties = Maps.newHashMap();\n\n  BaseTableCreationSparkAction(\n      SparkSession spark, CatalogPlugin sourceCatalog, Identifier sourceTableIdent) {\n    super(spark);\n\n    this.sourceCatalog = checkSourceCatalog(sourceCatalog);\n    this.sourceTableIdent = sourceTableIdent;\n\n    try {\n      this.sourceTable = (V1Table) this.sourceCatalog.loadTable(sourceTableIdent);\n      this.sourceCatalogTable = sourceTable.v1Table();\n    } catch (org.apache.spark.sql.catalyst.analysis.NoSuchTableException e) {\n      throw new NoSuchTableException(\"Cannot find source table '%s'\", sourceTableIdent);\n    } catch (ClassCastException e) {\n      throw new IllegalArgumentException(\n          String.format(\"Cannot use non-v1 table '%s' as a source\", sourceTableIdent), e);\n    }\n    validateSourceTable();\n\n    this.sourceTableLocation =\n        CatalogUtils.URIToString(sourceCatalogTable.storage().locationUri().get());\n  }\n\n  protected abstract TableCatalog checkSourceCatalog(CatalogPlugin catalog);\n\n  protected abstract StagingTableCatalog destCatalog();\n\n  protected abstract Identifier destTableIdent();\n\n  protected abstract Map<String, String> destTableProps();\n\n  protected String sourceTableLocation() {\n    return sourceTableLocation;","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/BaseTableCreationSparkAction.java#L65-L101","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nCALL iceberg.system.migrate('my_catalog.my_db.my_table')\n// after\nCALL iceberg.system.migrate('my_db.my_hive_table')  -- resolved via spark_catalog (V1Table)","handlingStrategy":"validation","validationCode":"// Verify the source resolves to a V1Table before running the procedure\nvar catalog = spark.sessionState().catalogManager().catalog(\"spark_catalog\");\nvar table = catalog.loadTable(Identifier.of(new String[]{\"db\"}, \"tbl\"));\nif (!(table instanceof org.apache.spark.sql.execution.datasources.v2.V1Table)) {\n  throw new IllegalStateException(\"Source is not a V1 (session catalog) table\");\n}","typeGuard":"function isV1Source(table) { return table instanceof org.apache.spark.sql.execution.datasources.v2.V1Table; }","tryCatchPattern":null,"preventionTips":["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"],"tags":["spark","catalog","type-cast","table-migration"],"backgroundTag":"incompatible-source-type","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}