{"record":{"id":"836425cabaeab3a6","repo":"apache/iceberg","slug":"cannot-add-partition-field-to-non-iceberg-table-836425","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.1/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.1/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/AddPartitionFieldExec.scala#L30-L59","documentation":"The AddPartitionFieldExec physical plan node commits an updateSpec().addField(...) only when the resolved table is an Iceberg table (a match on iceberg.table). Any other Table implementation falls into the catch-all case and gets this UnsupportedOperationException, because partition-field evolution is Iceberg-specific.","triggerScenarios":"Running `ALTER TABLE ... ADD PARTITION FIELD ...` against a table whose Spark catalog returns a non-Iceberg Table (e.g. a plain Spark V2 table such as Parquet/ORC/JSON datasources, or a non-Iceberg catalog provider).","commonSituations":"Pointing at the wrong catalog in a multi-catalog setup (using spark_catalog / built-in catalog instead of the Iceberg catalog), accidentally targeting a Hive or Delta table, or misconfiguring spark.sql.catalog.<name> so the extension plans run but resolution yields a foreign table.","solutions":["Verify the table lives in an Iceberg catalog: check spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog and the catalog used in the table name.","Use the fully-qualified name with the Iceberg catalog prefix, e.g. `iceberg_catalog.db.t`.","Confirm the underlying table is actually Iceberg (check metadata location in Hive metastore) — if not, migrate it before adding partition fields.","If you intended plain Spark tables, note ADD PARTITION FIELD is not supported there; use partitioning at write time instead."],"exampleFix":"-- before (plain catalog)\nALTER TABLE spark_catalog.db.t ADD PARTITION FIELD days(ts)\n-- after (Iceberg catalog)\nALTER TABLE iceberg_catalog.db.t ADD PARTITION FIELD days(ts)","handlingStrategy":"type-guard","validationCode":"// Scala: verify the table resolves through an Iceberg catalog first\nval isIceberg = spark.conf.get(\"spark.sql.catalog.iceberg_catalog\")\n  .contains(\"org.apache.iceberg.spark.SparkCatalog\")\nassert(isIceberg, \"ADD PARTITION FIELD requires an Iceberg catalog\")","typeGuard":"// Scala\n table match {\n  case t: org.apache.iceberg.spark.SparkTable => // Iceberg path\n  case _ => // non-Iceberg: skip or fail fast\n}","tryCatchPattern":"// Scala\ntry {\n  spark.sql(s\"ALTER TABLE $ident ADD PARTITION FIELD days(ts)\")\n} catch {\n  case _: UnsupportedOperationException => log.warn(s\"$ident is not an Iceberg table; skipping spec evolution\")\n}","preventionTips":["Always qualify table names with the Iceberg catalog prefix.","Check spark.sql.catalog.<name> points to Iceberg's SparkCatalog.","Verify table format before running Iceberg-specific DDL in batch scripts."],"tags":["spark","unsupported-operation","non-iceberg-table"],"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"}