apache/iceberg · error · AlreadyExistsException

View already exists: %s.%s

Error message

View already exists: %s.%s

What it means

doCommit maps Hive metastore's org.apache.hadoop.hive.metastore.api.AlreadyExistsException to Iceberg's AlreadyExistsException with "View already exists: database.viewName". This is raised when the metastore rejects the create/alter because an object with that name already exists, e.g., a concurrent create won the race.

Source

Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HiveViewOperations.java:203

          currentMetadataLocation(),
          sqlFor(metadata));
      lock.ensureActive();

      try {
        persistTable(tbl, updateHiveView, hiveLockEnabled(conf) ? null : baseMetadataLocation);
        lock.ensureActive();

        commitStatus = CommitStatus.SUCCESS;
      } catch (LockException le) {
        commitStatus = CommitStatus.UNKNOWN;
        throw new CommitStateUnknownException(
            "Failed to heartbeat for hive lock while "
                + "committing changes. This can lead to a concurrent commit attempt be able to overwrite this commit. "
                + "Please check the commit history. If you are running into this issue, try reducing "
                + "iceberg.hive.lock-heartbeat-interval-ms.",
            le);
      } catch (org.apache.hadoop.hive.metastore.api.AlreadyExistsException e) {
        throw new AlreadyExistsException(e, "View already exists: %s.%s", database, viewName);

      } catch (InvalidObjectException e) {
        throw new ValidationException(e, "Invalid Hive object for %s.%s", database, viewName);

      } catch (CommitFailedException | CommitStateUnknownException e) {
        throw e;

      } catch (Throwable e) {
        if (e.getMessage() != null
            && e.getMessage()
                .contains(
                    "The table has been modified. The parameter value for key '"
                        + BaseMetastoreTableOperations.METADATA_LOCATION_PROP
                        + "' is")) {
          throw new CommitFailedException(
              e, "The view %s.%s has been modified concurrently", database, viewName);
        }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Catch AlreadyExistsException and fall back to loading or replacing the existing view.
  2. Check existence first with catalog.viewExists, but keep the catch for the inherent race.
  3. Pick a different view name or drop the conflicting object intentionally before creating.
  4. Deduplicate DDL submissions in your orchestration to avoid double creates.

Example fix

// before
views.createView(identifier, ...); // AlreadyExistsException on race
// after
try {
  views.createView(identifier, ...);
} catch (AlreadyExistsException e) {
  views.loadView(identifier); // adopt existing
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (catalog.viewExists(identifier)) {
  throw new IllegalStateException("View " + identifier + " already exists; use replace instead of create");
}

Try / catch

try {
  views.createView(identifier, ...);
} catch (AlreadyExistsException e) {
  views.loadView(identifier); // adopt or replaceView instead
}

Prevention

When it happens

Trigger: Committing a view creation when HMS raises its native AlreadyExistsException — an object (view or table) named database.viewName already exists in the metastore at alter/create time.

Common situations: Concurrent view creation by two clients; retrying create after an ambiguous first attempt that actually succeeded; name collisions with existing tables; double submission of the same DDL job.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/604c070b0a81f806. Report an issue: GitHub.