apache/iceberg · error · ViewAlreadyExistsException

View already exists

Error message

View already exists: ${ident}

What it means

Thrown by SparkCatalog.createView when the underlying view catalog already contains a view with the same identifier. The Iceberg AlreadyExistsException is translated into a Spark ViewAlreadyExistsException. CREATE VIEW without IF NOT EXISTS always fails on an existing name.

Solutions

  1. Use CREATE VIEW IF NOT EXISTS, or drop/rename the existing view first
  2. In code, check catalog.viewExists(ident) before createView, or catch ViewAlreadyExistsException
  3. Switch to replaceView (CREATE OR REPLACE VIEW) when overwriting is intended
  4. Choose a distinct view name if the collision is accidental

Example fix

// before
spark.sql("CREATE VIEW prod.db.report AS SELECT ...") // View already exists
// after
spark.sql("CREATE OR REPLACE VIEW prod.db.report AS SELECT ...")
Defensive patterns

Strategy: try-catch

Validate before calling

Identifier ident = Identifier.of(new String[]{"db"}, "report");
if (viewCatalog.viewExists(ident)) {
  viewCatalog.dropView(ident); // or use replaceView
}

Type guard

boolean viewIsFree(ViewCatalog catalog, Identifier ident) {
  return !catalog.viewExists(ident);
}

Try / catch

try {
  spark.sql("CREATE VIEW " + ident + " AS " + sql);
} catch (ViewAlreadyExistsException e) {
  LOG.info("View {} exists, replacing", ident);
  spark.sql("CREATE OR REPLACE VIEW " + ident + " AS " + sql);
}

Prevention

When it happens

Trigger: CREATE VIEW on an identifier that already exists as a view; programmatic catalog.createView(...) without checking existence; a race where two sessions create the same view simultaneously.

Common situations: Re-running idempotency-naive migration/deployment scripts; name collision between views in the same namespace; residual view left by a partially rolled-back pipeline.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/a437fdda2f290e07. Report an issue: GitHub.

Appendix: source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:644

                .putAll(Spark3Util.rebuildCreateProperties(properties))
                .put(SparkView.QUERY_COLUMN_NAMES, COMMA_JOINER.join(queryColumnNames))
                .buildKeepingLast();

        org.apache.iceberg.view.View view =
            asViewCatalog
                .buildView(buildIdentifier(ident))
                .withDefaultCatalog(currentCatalog)
                .withDefaultNamespace(Namespace.of(currentNamespace))
                .withQuery("spark", sql)
                .withSchema(icebergSchema)
                .withLocation(properties.get("location"))
                .withProperties(props)
                .create();
        return new SparkView(catalogName, view);
      } catch (org.apache.iceberg.exceptions.NoSuchNamespaceException e) {
        throw new NoSuchNamespaceException(currentNamespace);
      } catch (AlreadyExistsException e) {
        throw new ViewAlreadyExistsException(ident);
      }
    }

    throw new UnsupportedOperationException(
        "Creating a view is not supported by catalog: " + catalogName);
  }

  @Override
  public View replaceView(
      Identifier ident,
      String sql,
      String currentCatalog,
      String[] currentNamespace,
      StructType schema,
      String[] queryColumnNames,
      String[] columnAliases,
      String[] columnComments,
      Map<String, String> properties)

View on GitHub (pinned to 86d9c8fc54)