apache/iceberg · error · AlreadyExistsException
View with same name already exists: %s
Error message
View with same name already exists: %s
What it means
An AlreadyExistsException thrown by the view Builder's replaceTransaction() in RESTSessionCatalog when a view with the same identifier already exists on the server. replaceTransaction is meant to atomically replace an existing view; if the name resolves to a view, the operation conflicts and is rejected before sending the replacement request.
Source
Thrown at core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java:1068
tableConf,
response.credentials(),
response.remoteSigningConfig()),
RESTTableOperations.UpdateType.CREATE,
createChanges(meta),
meta,
endpoints);
trackFileIO(ops);
return Transactions.createTableTransaction(
fullName, ops, meta, metricsReporter(paths.metrics(ident), tableClient));
}
@Override
public Transaction replaceTransaction() {
Endpoint.check(endpoints, Endpoint.V1_UPDATE_TABLE);
if (viewExists(context, ident)) {
throw new AlreadyExistsException("View with same name already exists: %s", ident);
}
LoadTableResponse response = loadInternal(context, ident, snapshotMode, Map.of(), h -> {});
String fullName = fullTableName(ident);
Map<String, String> tableConf = response.config();
AuthSession contextualSession = authManager.contextualSession(context, catalogAuth);
AuthSession tableSession = authManager.tableSession(ident, tableConf, contextualSession);
TableMetadata base = response.tableMetadata();
propertiesBuilder.putAll(tableOverrideProperties());
Map<String, String> tableProperties = propertiesBuilder.buildKeepingLast();
TableMetadata replacement =
base.buildReplacement(
schema,
spec != null ? spec : PartitionSpec.unpartitioned(),
writeOrder != null ? writeOrder : SortOrder.unsorted(),View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check catalog.viewExists(identifier) first and decide whether replace, create, or drop is intended.
- Catch org.apache.iceberg.exceptions.AlreadyExistsException and handle the conflict explicitly.
- Use dropView then createView if unconditional replacement semantics are desired (non-atomically).
- Verify the identifier/namespace resolution — the existing view may be under a different resolved namespace than expected.
Example fix
// before
viewBuilder(ident).replaceTransaction().commitTransaction();
// after
if (!catalog.viewExists(ident)) { /* create */ } else { catalog.loadView(ident).replace().commit(); } Defensive patterns
Strategy: validation
Validate before calling
if (catalog.viewExists(identifier)) { /* handle existing view: replace() vs skip vs drop */ } Try / catch
try { builder.replaceTransaction().commitTransaction(); } catch (AlreadyExistsException e) { /* view already exists: resolve conflict */ } Prevention
- Check viewExists before replaceTransaction
- Standardize on explicit create-or-replace logic with conflict handling
- Catch AlreadyExistsException around concurrent replace flows
- Confirm namespace resolution matches where the view actually lives
When it happens
Trigger: Calling viewBuilder(...).replaceTransaction() (or SQL CREATE OR REPLACE via this path) when viewExists(context, ident) is true — i.e., the target name is an existing view.
Common situations: Concurrent CREATE OR REPLACE VIEW statements racing on the same view name; a script that assumes the view does not exist; namespace confusion where the view already exists under a resolved default namespace.
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
- Table with same name already exists: %s
- View with same name already exists: %s
- ViewAlreadyExistsException(ident)
- View already exists: ${toIdentifier}
- Cannot create namespace %s: already exists
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/926948c1f22d1108.
Report an issue: GitHub.