apache/iceberg · error
Cannot move view between catalogs: from=
Error message
Cannot move view between catalogs: from=${oldCatalog.name} and to=${newIdent.catalog().name()} What it means
ExtendedDataSourceV2Strategy throws this AnalysisException when ALTER VIEW ... RENAME TO resolves to a different catalog than the one holding the original view. Iceberg's ViewCatalog supports renaming views only within the same catalog; cross-catalog moves are not implemented. The strategy compares oldCatalog.name with the catalog parsed from the new name and fails fast before building the RenameV2ViewExec.
Solutions
- Rename within the same catalog: ALTER VIEW cat1.db.v RENAME TO cat1.db.v2.
- To move a catalog, create the view in the target catalog (CREATE VIEW ... AS SELECT * FROM old) and drop the original.
- Remove the unintended catalog prefix so the new name resolves to the source catalog.
- Check Spark3Util.catalogAndIdentifier output by logging/spark.sql which catalog the new name binds to.
Example fix
-- before ALTER VIEW cat1.db.metrics_summary RENAME TO cat2.db.metrics_summary; -- after ALTER VIEW cat1.db.metrics_summary RENAME TO cat1.db.metrics_summary_v2;
Defensive patterns
Strategy: validation
Validate before calling
val target = Spark3Util.catalogAndIdentifier(spark, newName)
if (target.catalog().name() != sourceCatalogName) throw new AnalysisException("rename must stay within the source catalog") Try / catch
try { spark.sql(s"ALTER VIEW $oldName RENAME TO $newName") } catch { case e: org.apache.spark.sql.AnalysisException if e.getMessage.contains("Cannot move view between catalogs") => log.error("cross-catalog view rename unsupported; recreate view instead") } Prevention
- Never include a different catalog prefix in the RENAME TO name
- To relocate a view, CREATE VIEW in the target catalog then DROP the original
- Remember the session default catalog is used when the new name has no catalog prefix
When it happens
Trigger: ALTER VIEW cat1.db.v RENAME TO cat2.db.v2 where Spark3Util.catalogAndIdentifier resolves the new name to catalog cat2, different from the view's source catalog cat1.
Common situations: Users assuming RENAME can move views across catalogs like a copy+drop; default-catalog resolution silently picking the session catalog instead of the source catalog; migration scripts rewriting view names with a different catalog prefix.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Renaming a view is not supported by catalog
- ALTER VIEW AS is not supported. Use CREATE OR REPLACE VIEW…
- ALTER VIEW AS is not supported. Use CREATE OR REPLACE VIEW…
- ALTER VIEW AS is not supported. Use CREATE OR REPLACE VIEW…
- Altering a view is not supported by catalog
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/af94822ccfddfb27.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/ExtendedDataSourceV2Strategy.scala:132
case SetIdentifierFields(IcebergCatalogAndIdentifier(catalog, ident), fields) =>
SetIdentifierFieldsExec(catalog, ident, fields) :: Nil
case DropIdentifierFields(IcebergCatalogAndIdentifier(catalog, ident), fields) =>
DropIdentifierFieldsExec(catalog, ident, fields) :: Nil
case SetWriteDistributionAndOrdering(
IcebergCatalogAndIdentifier(catalog, ident),
distributionMode,
ordering) =>
SetWriteDistributionAndOrderingExec(catalog, ident, distributionMode, ordering) :: Nil
case OrderAwareCoalesce(numPartitions, coalescer, child) =>
OrderAwareCoalesceExec(numPartitions, coalescer, planLater(child)) :: Nil
case RenameTable(ResolvedV2View(oldCatalog: ViewCatalog, oldIdent), newName, isView @ true) =>
val newIdent = Spark3Util.catalogAndIdentifier(spark, newName.toList.asJava)
if (oldCatalog.name != newIdent.catalog().name()) {
throw new AnalysisException(
s"Cannot move view between catalogs: from=${oldCatalog.name} and to=${newIdent.catalog().name()}")
}
RenameV2ViewExec(oldCatalog, oldIdent, newIdent.identifier()) :: Nil
case DropIcebergView(ResolvedIdentifier(viewCatalog: ViewCatalog, ident), ifExists) =>
DropV2ViewExec(viewCatalog, ident, ifExists) :: Nil
case CreateIcebergView(
ResolvedIdentifier(viewCatalog: ViewCatalog, ident),
queryText,
query,
columnAliases,
columnComments,
queryColumnNames,
comment,
properties,
allowExisting,
replace,View on GitHub (pinned to 86d9c8fc54)