{"record":{"id":"461d986af14c3136","repo":"apache/iceberg","slug":"replacing-a-view-is-not-supported-by-catalog-cata","errorCode":null,"errorMessage":"Replacing a view is not supported by catalog: catalogName","messagePattern":"Replacing a view is not supported by catalog: catalogName","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java","lineNumber":689,"sourceCode":"        org.apache.iceberg.view.View view =\n            asViewCatalog\n                .buildView(buildIdentifier(ident))\n                .withDefaultCatalog(currentCatalog)\n                .withDefaultNamespace(Namespace.of(currentNamespace))\n                .withQuery(\"spark\", sql)\n                .withSchema(icebergSchema)\n                .withLocation(properties.get(\"location\"))\n                .withProperties(props)\n                .createOrReplace();\n        return new SparkView(catalogName, view);\n      } catch (org.apache.iceberg.exceptions.NoSuchNamespaceException e) {\n        throw new NoSuchNamespaceException(currentNamespace);\n      } catch (org.apache.iceberg.exceptions.NoSuchViewException e) {\n        throw new NoSuchViewException(ident);\n      }\n    }\n\n    throw new UnsupportedOperationException(\n        \"Replacing a view is not supported by catalog: \" + catalogName);\n  }\n\n  @Override\n  public View alterView(Identifier ident, ViewChange... changes)\n      throws NoSuchViewException, IllegalArgumentException {\n    if (null != asViewCatalog) {\n      try {\n        org.apache.iceberg.view.View view = asViewCatalog.loadView(buildIdentifier(ident));\n        UpdateViewProperties updateViewProperties = view.updateProperties();\n\n        for (ViewChange change : changes) {\n          if (change instanceof ViewChange.SetProperty) {\n            ViewChange.SetProperty property = (ViewChange.SetProperty) change;\n            verifyNonReservedPropertyIsSet(property.property());\n            updateViewProperties.set(property.property(), property.value());\n          } else if (change instanceof ViewChange.RemoveProperty) {\n            ViewChange.RemoveProperty remove = (ViewChange.RemoveProperty) change;","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java#L671-L707","documentation":"SparkCatalog.replaceView throws UnsupportedOperationException when the wrapped catalog does not implement the Iceberg ViewCatalog interface (asViewCatalog is null). Since views cannot even be loaded by such a catalog, CREATE OR REPLACE VIEW cannot be executed, and the unsupported catalog name is reported.","triggerScenarios":"Executing CREATE OR REPLACE VIEW (routed to replaceView at SparkCatalog.java:650) against a table-only Iceberg catalog such as HadoopCatalog (spark.sql.catalog.<name>=org.apache.iceberg.hadoop.HadoopCatalog) or a custom Catalog without ViewCatalog support.","commonSituations":"Migration of view-based pipelines from Hive/JDBC catalogs to environments configured with HadoopCatalog; notebooks that hardcode a catalog URI but change the catalog class; Spark 3.4+ view DDL run on older catalog configs.","solutions":["Configure spark.sql.catalog.<name> with a ViewCatalog implementation (HiveCatalog, JdbcCatalog, RESTCatalog, NessieCatalog).","Replace view-refresh logic with table-based flows (e.g. INSERT OVERWRITE into an Iceberg table) if stuck on a table-only catalog.","Implement org.apache.iceberg.catalog.ViewCatalog in your custom catalog to support view replacement.","Route view DDL to a different, view-capable catalog in the same session."],"exampleFix":"// before\nspark.conf.set(\"spark.sql.catalog.etl\", \"org.apache.iceberg.hadoop.HadoopCatalog\");\nspark.sql(\"CREATE OR REPLACE VIEW etl.ns.v AS SELECT ...\"); // UnsupportedOperationException\n\n// after\nspark.conf.set(\"spark.sql.catalog.etl\", \"org.apache.iceberg.rest.RESTCatalog\");\nspark.sql(\"CREATE OR REPLACE VIEW etl.ns.v AS SELECT ...\");","handlingStrategy":"validation","validationCode":"Catalog catalog = Spark3Util.loadIcebergCatalog(spark, catalogName);\nif (!(catalog instanceof ViewCatalog)) {\n  throw new IllegalStateException(\"CREATE OR REPLACE VIEW unsupported on catalog \" + catalogName);\n}","typeGuard":"boolean supportsViewReplace(Catalog catalog) {\n  return catalog instanceof org.apache.iceberg.catalog.ViewCatalog;\n}","tryCatchPattern":"try {\n  spark.sql(\"CREATE OR REPLACE VIEW \" + ident + \" AS \" + sqlText);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"Replacing a view is not supported\")) {\n    // route to a view-capable catalog or use table overwrite\n  }\n}","preventionTips":["Audit catalog class configs for ViewCatalog support before adopting view-refresh pipelines.","Centralize catalog selection so view workloads cannot run against table-only catalogs.","Document per-catalog capability (views vs tables only) for your environments.","Test view DDL against each environment's actual catalog class in CI."],"tags":["spark","view-catalog","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"}