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

  1. Catch AlreadyExistsException and load the existing view instead of creating it (create-or-replace semantics via replaceView).
  2. Use catalog-level existence checks (catalog.viewExists) before create, accepting the race and handling the exception.
  3. Rename your view or choose a different namespace if the collision is with an unintended table.
  4. 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

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


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