apache/iceberg · error · AlreadyExistsException

Table with same name already exists: %s

Error message

Table with same name already exists: %s

What it means

HiveCatalog's table-builder createOrReplace() throws AlreadyExistsException when a table (not a view) already exists under the target identifier. createOrReplace on a view builder refuses to clobber an existing table — replacing a table with a view would destroy data, so it is a hard error. The tableExists check runs before any replacement metadata is committed.

Source

Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HiveCatalog.java:943

  /**
   * The purpose of this class is to add table detection only for Hive-Specific view. Hive catalog
   * follows checks at different levels: 1. During refresh, it validates if the view is an iceberg
   * view or not. 2. During commit, it validates if there is any concurrent commit with view or
   * view-name already exists. This class helps to do the validation on an early basis.
   */
  private class TableAwareViewBuilder extends BaseViewBuilder {

    private final TableIdentifier identifier;

    private TableAwareViewBuilder(TableIdentifier identifier) {
      super(identifier);
      this.identifier = identifier;
    }

    @Override
    public View createOrReplace() {
      if (tableExists(identifier)) {
        throw new AlreadyExistsException("Table with same name already exists: %s", identifier);
      }
      return super.createOrReplace();
    }

    @Override
    public View create() {
      if (tableExists(identifier)) {
        throw new AlreadyExistsException("Table with same name already exists: %s", identifier);
      }
      return super.create();
    }
  }

  /**
   * Register a table with the catalog if it does not exist. This is overridden in order to add view
   * existence detection before registering a table.
   *
   * @param identifier a table identifier

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Drop the existing table explicitly: catalog.dropTable(identifier) (consider purge semantics) before creating the view.
  2. Choose a distinct identifier for the view so it doesn't collide with the table.
  3. Catch AlreadyExistsException and surface a clear operator message about the table/view name collision.
  4. Audit the namespace for name collisions before running view-creation migrations.

Example fix

// before
catalog.buildView(identifier).createOrReplace(); // collides with existing table
// after
if (catalog.tableExists(identifier)) {
  catalog.dropTable(identifier);
}
catalog.buildView(identifier).createOrReplace();
Defensive patterns

Strategy: validation

Validate before calling

if (catalog.tableExists(identifier)) {
  throw new IllegalStateException("Name " + identifier + " is occupied by a table; cannot create view");
}

Try / catch

try {
  catalog.buildView(identifier).createOrReplace();
} catch (AlreadyExistsException e) {
  // drop the table explicitly after human confirmation, then retry
}

Prevention

When it happens

Trigger: Calling HiveCatalog.buildView(identifier).createOrReplace() when a table with the same namespace/name exists (tableExists(identifier) is true). Typically a name collision where the same logical name was previously created as a table.

Common situations: Migrating a dataset from a table to a view without dropping the table first; a naming convention change that collides an old table name with a new view name; automated scripts reusing one identifier for both artifacts.

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/33eadeaae3cc8e83. Report an issue: GitHub.