apache/iceberg · error · AlreadyExistsException
Table with same name already exists: %s
Error message
Table with same name already exists: %s
What it means
An AlreadyExistsException thrown by the view Builder's replace() in RESTSessionCatalog when the target identifier currently resolves to a TABLE, not a view. Replacing a view cannot overwrite a table of the same name, so the operation is rejected before loading the view.
Source
Thrown at core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java:1777
response.metadata(),
endpoints);
return new BaseView(ops, ViewUtil.fullViewName(name(), identifier));
}
@Override
public View createOrReplace() {
try {
return replace(loadView());
} catch (NoSuchViewException e) {
return create();
}
}
@Override
public View replace() {
if (tableExists(context, identifier)) {
throw new AlreadyExistsException("Table with same name already exists: %s", identifier);
}
return replace(loadView());
}
private LoadViewResponse loadView() {
Endpoint.check(
endpoints,
Endpoint.V1_LOAD_VIEW,
() ->
new NoSuchViewException(
"Unable to load view %s.%s: Server does not support endpoint %s",
name(), identifier, Endpoint.V1_LOAD_VIEW));
AuthSession contextualSession = authManager.contextualSession(context, catalogAuth);
return client
.withAuthSession(contextualSession)
.get(View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check catalog.tableExists(identifier) before replace and pick a different name or drop the table first.
- Catch org.apache.iceberg.exceptions.AlreadyExistsException and surface the naming conflict to the user.
- Verify the intended object type with loadTable vs loadView to confirm what exists at that name.
- Use distinct naming conventions for tables vs views to avoid collisions.
Example fix
// before
catalog.buildView(ident).replace().createView(); // fails if a table named ident exists
// after
if (catalog.tableExists(ident)) { throw new IllegalStateException("name taken by table: " + ident); }
catalog.buildView(ident).replace().createView(); Defensive patterns
Strategy: validation
Validate before calling
if (catalog.tableExists(identifier)) { throw new IllegalStateException("cannot replace view: name held by table " + identifier); } Try / catch
try { viewBuilder.replace().createView(); } catch (AlreadyExistsException e) { /* name occupied by a table */ } Prevention
- Check tableExists before building a replacing view
- Use separate naming conventions for tables and views
- Catch AlreadyExistsException on view replace flows
- Audit namespaces for mixed table/view name collisions during migrations
When it happens
Trigger: Calling viewBuilder(identifier).replace() when tableExists(context, identifier) is true — i.e., a table already occupies that name in the catalog.
Common situations: Name collision between tables and views in the same namespace; a migration script recreating a view where a table was created; namespace confusion after default-namespace resolution.
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 already exists: %s
- Table already exists: %s
- View with same name already exists: %s
- ViewAlreadyExistsException(ident)
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/a3dd3951729fa8c2.
Report an issue: GitHub.