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
- Use CREATE VIEW IF NOT EXISTS, or drop/rename the existing view first
- In code, check catalog.viewExists(ident) before createView, or catch ViewAlreadyExistsException
- Switch to replaceView (CREATE OR REPLACE VIEW) when overwriting is intended
- 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
- Prefer CREATE OR REPLACE VIEW when overwriting is acceptable
- Use IF NOT EXISTS when the create is idempotent provisioning
- Generate unique view names per run in ephemeral/CI environments
- Check viewExists before createView in programmatic pipelines
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
- Namespace not found
- NoSuchNamespaceException(currentNamespace)
- Altering a view is not supported by catalog:
- Altering a view is not supported by catalog
- Altering a view is not supported by catalog
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)