apache/iceberg · error · AlreadyExistsException
View already exists: %s
Error message
View already exists: %s
What it means
BaseViewBuilder.create commits a new view but first checks ViewOperations.current(). If view metadata already exists, it throws AlreadyExistsException because create() must not overwrite an existing view (use createOrReplace or replace for that).
Source
Thrown at core/src/main/java/org/apache/iceberg/view/BaseMetastoreViewCatalog.java:184
@Override
public View replace() {
return replace(newViewOps(identifier));
}
@Override
public View createOrReplace() {
ViewOperations ops = newViewOps(identifier);
if (null == ops.current()) {
return create(ops);
} else {
return replace(ops);
}
}
private View create(ViewOperations ops) {
if (null != ops.current()) {
throw new AlreadyExistsException("View already exists: %s", identifier);
}
Preconditions.checkState(
!representations.isEmpty(), "Cannot create view without specifying a query");
Preconditions.checkState(null != schema, "Cannot create view without specifying schema");
Preconditions.checkState(
null != defaultNamespace, "Cannot create view without specifying a default namespace");
ViewVersion viewVersion =
ImmutableViewVersion.builder()
.versionId(1)
.schemaId(schema.schemaId())
.addAllRepresentations(representations)
.defaultNamespace(defaultNamespace)
.defaultCatalog(defaultCatalog)
.timestampMillis(System.currentTimeMillis())
.putAllSummary(EnvironmentContext.get())
.build();View on GitHub (pinned to 86d9c8fc54)
Solutions
- Use createOrReplace(...) instead of create(...) when overwriting is intended
- Drop the existing view first (catalog.dropView(identifier))
- Use catalog.viewExists(identifier) as an existence guard before create
Example fix
// before
catalog.buildView(ident).withQuery("sql", "select 1").create();
// after
catalog.buildView(ident).withQuery("sql", "select 1").createOrReplace(); Defensive patterns
Strategy: try-catch
Validate before calling
if (catalog.viewExists(identifier) && !allowOverwrite) { throw new IllegalStateException("View " + identifier + " already exists"); } Try / catch
try { return builder.create(); } catch (AlreadyExistsException e) { return catalog.loadView(identifier); /* idempotent create */ } Prevention
- Prefer createOrReplace for repeatable DDL scripts
- Check viewExists before create in setup code
- Serialize view DDL through one job/lock
When it happens
Trigger: Calling catalog.buildView(ident)...create() (or createOrReplace where the replace branch routes here) when a view with that identifier already exists in the metastore.
Common situations: Race between two jobs creating the same view name; rerunning idempotent setup scripts without createOrReplace; leftover view from a previous run.
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
- View with same name already exists: %s
- Table with same name already exists: %s
- Cannot rename %s to %s. View already exists
- Cannot create namespace %s: already exists
- Cannot rename table %s to %s: %s already exists
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/204b95e8ac389844.
Report an issue: GitHub.