apache/iceberg · error · AlreadyExistsException
%s already exists: %s.%s
Error message
%s already exists: %s.%s
What it means
HiveViewOperations.doCommit throws AlreadyExistsException when attempting to create a new view but the HMS table already exists and has a METADATA_LOCATION_PROP set. If the existing object is a VIRTUAL_VIEW it reports a "view already exists", otherwise a "table already exists" — this detects a concurrent create that won the race.
Source
Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HiveViewOperations.java:140
String newMetadataLocation = writeNewMetadataIfRequired(metadata);
boolean hiveEngineEnabled = false;
CommitStatus commitStatus = CommitStatus.FAILURE;
boolean updateHiveView = false;
HiveLock lock = lockObject();
try {
lock.lock();
Table tbl = loadHmsTable();
if (tbl != null) {
// If we try to create the view but the metadata location is already set, then we had a
// concurrent commit
if (newView
&& tbl.getParameters().get(BaseMetastoreTableOperations.METADATA_LOCATION_PROP)
!= null) {
throw new AlreadyExistsException(
"%s already exists: %s.%s",
TableType.VIRTUAL_VIEW.name().equalsIgnoreCase(tbl.getTableType())
? ContentType.VIEW.value()
: ContentType.TABLE.value(),
database,
viewName);
}
updateHiveView = true;
LOG.debug("Committing existing view: {}", fullName);
} else {
tbl = newHMSView(metadata);
LOG.debug("Committing new view: {}", fullName);
}
tbl.setSd(
HiveOperationsBase.storageDescriptor(
metadata.schema(),View on GitHub (pinned to 86d9c8fc54)
Solutions
- Catch AlreadyExistsException and load the existing view instead of creating it (create-or-replace semantics via replaceView).
- Use catalog-level existence checks (catalog.viewExists) before create, accepting the race and handling the exception.
- Rename your view or choose a different namespace if the collision is with an unintended table.
- Coordinate DDL across jobs (external locking or orchestration) to avoid concurrent creates.
Example fix
// before
views.createView(identifier, schema, spec, null, location, props); // races
// after
try {
views.createView(identifier, schema, spec, null, location, props);
} catch (AlreadyExistsException e) {
View existing = views.loadView(identifier); // use or replace existing
} Defensive patterns
Strategy: try-catch
Validate before calling
if (catalog.viewExists(identifier)) {
// decide: adopt, replace, or abort instead of creating
} Try / catch
try {
views.createView(identifier, schema, spec, null, location, props);
} catch (AlreadyExistsException e) {
View existing = views.loadView(identifier); // handle concurrent create
} Prevention
- Use idempotent create-or-replace flows rather than blind create.
- Serialize concurrent DDL on the same view name via orchestration.
- Deduplicate retried create jobs.
- Avoid reusing names across views and tables in the same database.
When it happens
Trigger: Calling createView (doCommit with newView=true) while another client concurrently created the same view (or a table with the same name) in the metastore, so the HMS getView/alter path finds an existing object with metadata location already set.
Common situations: Two jobs creating the same view concurrently; retrying a create after an ambiguous failure when the first attempt actually succeeded; name collision between a view and an existing table in the same database.
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.%s
- View already exists: %s.%s
- View already exists: %s
- View already exists: %s
- Table already exists: %s.%s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/0e455b4d22b3094c.
Report an issue: GitHub.