{"record":{"id":"9eebe0d9313d16e2","repo":"apache/iceberg","slug":"cannot-replace-partition-field-in-non-iceberg-tabl","errorCode":null,"errorMessage":"Cannot replace partition field in non-Iceberg table: $table","messagePattern":"Cannot replace partition field in non-Iceberg table: \\$table","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/ReplacePartitionFieldExec.scala","lineNumber":65,"sourceCode":"          case IdentityTransform(FieldReference(parts))\n              if parts.size == 1 && schema.findField(parts.head) == null =>\n            // the name is not present in the Iceberg schema, so it must be a partition field name, not a column name\n            iceberg.table\n              .updateSpec()\n              .removeField(parts.head)\n              .addField(name.orNull, Spark3Util.toIcebergTerm(transformTo))\n              .commit()\n\n          case _ =>\n            iceberg.table\n              .updateSpec()\n              .removeField(Spark3Util.toIcebergTerm(transformFrom))\n              .addField(name.orNull, Spark3Util.toIcebergTerm(transformTo))\n              .commit()\n        }\n\n      case table =>\n        throw new UnsupportedOperationException(\n          s\"Cannot replace partition field in non-Iceberg table: $table\")\n    }\n\n    Nil\n  }\n\n  override def simpleString(maxFields: Int): String = {\n    s\"ReplacePartitionField ${catalog.name}.${ident.quoted} ${transformFrom.describe} \" +\n      s\"with ${name.map(n => s\"$n=\").getOrElse(\"\")}${transformTo.describe}\"\n  }\n}\n","sourceCodeStart":47,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/ReplacePartitionFieldExec.scala#L47-L77","documentation":"ReplacePartitionFieldExec throws this UnsupportedOperationException when a REPLACE PARTITION FIELD statement targets a non-Iceberg table. Replacing a partition field uses Iceberg's updateSpec().removeField(...).addField(...) API, available only on SparkTable instances wrapping Iceberg tables. Other providers fall through to the throwing case.","triggerScenarios":"Running ALTER TABLE ... REPLACE PARTITION FIELD <from> WITH <to> where the resolved table is not an Iceberg SparkTable, so the `case iceberg: SparkTable` match fails.","commonSituations":"Partition-evolution DDL run against Hive/Delta tables; incorrect default catalog in multi-catalog sessions; generated migration scripts applying Iceberg spec changes to all tables regardless of provider.","solutions":["Confirm the table provider is iceberg via DESC TABLE EXTENDED.","Qualify with the Iceberg catalog: ALTER TABLE iceberg_catalog.db.tbl REPLACE PARTITION FIELD days(ts) WITH hours(ts).","Register the catalog with org.apache.iceberg.spark.SparkCatalog.","Filter scripts to Iceberg tables before applying partition evolution DDL."],"exampleFix":"-- before\nALTER TABLE db.events REPLACE PARTITION FIELD days(ts) WITH hours(ts); -- non-Iceberg\n-- after\nALTER TABLE iceberg_catalog.db.events REPLACE PARTITION FIELD days(ts) WITH hours(ts);","handlingStrategy":"validation","validationCode":"val provider = spark.sql(\"DESC TABLE EXTENDED cat.db.tbl\").where(\"col_name = 'Provider'\").first().getString(1)\nrequire(provider == \"iceberg\", \"REPLACE PARTITION FIELD requires Iceberg\")","typeGuard":"def supportsSpecEvolution(t: org.apache.spark.sql.connector.catalog.Table): Boolean = t.isInstanceOf[org.apache.iceberg.spark.source.SparkTable]","tryCatchPattern":"try { spark.sql(\"ALTER TABLE cat.db.tbl REPLACE PARTITION FIELD days(ts) WITH hours(ts)\") } catch { case e: UnsupportedOperationException if e.getMessage.contains(\"non-Iceberg\") => log.warn(\"target is not Iceberg\") }","preventionTips":["Qualify with the Iceberg catalog name in all partition evolution DDL","Assert provider before batch-running spec-change scripts","Keep partition-evolution tooling tied to Iceberg catalogs only"],"tags":["spark","iceberg","unsupported-operation","partitioning"],"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"}