{"record":{"id":"1d48afd7214a9f3b","repo":"apache/iceberg","slug":"cannot-add-partition-field-to-non-iceberg-table-1d48af","errorCode":null,"errorMessage":"Cannot add partition field to non-Iceberg table: $table","messagePattern":"Cannot add partition field to non-Iceberg table: \\$table","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/AddPartitionFieldExec.scala","lineNumber":48,"sourceCode":"    catalog: TableCatalog,\n    ident: Identifier,\n    transform: Transform,\n    name: Option[String])\n    extends LeafV2CommandExec {\n  import org.apache.spark.sql.connector.catalog.CatalogV2Implicits._\n\n  override lazy val output: Seq[Attribute] = Nil\n\n  override protected def run(): Seq[InternalRow] = {\n    catalog.loadTable(ident) match {\n      case iceberg: SparkTable =>\n        iceberg.table\n          .updateSpec()\n          .addField(name.orNull, Spark3Util.toIcebergTerm(transform))\n          .commit()\n\n      case table =>\n        throw new UnsupportedOperationException(\n          s\"Cannot add partition field to non-Iceberg table: $table\")\n    }\n\n    Nil\n  }\n\n  override def simpleString(maxFields: Int): String = {\n    s\"AddPartitionField ${catalog.name}.${ident.quoted} ${name.map(n => s\"$n=\").getOrElse(\"\")}${transform.describe}\"\n  }\n}\n","sourceCodeStart":30,"sourceCodeEnd":59,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/AddPartitionFieldExec.scala#L30-L59","documentation":"AddPartitionFieldExec applies partition-field evolution only when the resolved table is an Iceberg table exposing updateSpec(); for any other V2 catalog table the command pattern-match falls through and throws UnsupportedOperationException, because spec evolution has no meaning outside Iceberg's partition-spec model.","triggerScenarios":"Running `ALTER TABLE <v2_table> ADD PARTITION FIELD <transform>` where <v2_table> is backed by a non-Iceberg catalog (e.g. a Delta/JDBC/custom V2 catalog) so the Exec resolves to a generic table rather than an org.apache.iceberg.Table.","commonSituations":"Pointing ALTER TABLE ... ADD PARTITION FIELD at the wrong catalog or table type; running the Iceberg extension syntax against tables registered via Spark's generic V2 catalog; typos in catalog qualification so the Iceberg catalog isn't selected.","solutions":["Confirm the table is in an Iceberg catalog: run DESCRIBE TABLE / check the catalog implementation in your Spark session config (spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog).","Qualify the statement with the Iceberg catalog name: `ALTER TABLE iceberg_catalog.db.t ADD PARTITION FIELD ...`.","Use the target engine's own partitioning API if the table genuinely is not an Iceberg table.","If the table should be Iceberg, migrate/register it (e.g. via snapshot/import procedures) before evolving its spec."],"exampleFix":"-- before\nALTER TABLE spark_catalog.default.t ADD PARTITION FIELD days(ts)\n-- after\nALTER TABLE iceberg_cat.default.t ADD PARTITION FIELD days(ts)","handlingStrategy":"validation","validationCode":"// Ensure the target catalog is Iceberg before ADD PARTITION FIELD\nval isIceberg = spark.conf.get(s\"spark.sql.catalog.$catName\") == \"org.apache.iceberg.spark.SparkCatalog\"\nrequire(isIceberg, s\"Catalog $catName is not an Iceberg catalog\")","typeGuard":null,"tryCatchPattern":"try { spark.sql(s\"ALTER TABLE $t ADD PARTITION FIELD days(ts)\") } catch {\n  case e: UnsupportedOperationException if e.getMessage.contains(\"non-Iceberg table\") =>\n    log.error(s\"$t is not an Iceberg table; migrate or qualify with the Iceberg catalog name\")\n}","preventionTips":["Qualify tables with the Iceberg catalog name in DDL","Verify catalog configs (spark.sql.catalog.*) point to SparkCatalog/SparkSessionCatalog","Use DESCRIBE EXTENDED to confirm table provider before spec evolution","Register/migrate external tables into Iceberg before evolving their partition spec"],"tags":["spark","partition-spec","table-type","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}