apache/iceberg · error · AlreadyExistsException

Cannot rename %s to %s. View already exists

Error message

Cannot rename %s to %s. View already exists

What it means

JdbcCatalog.renameTable throws AlreadyExistsException when renaming a table to a name that collides with an existing view under the V1 schema. This guards the single-catalog-namespace against name collisions between tables and views in V1-backed JDBC catalogs. The rename is aborted before any SQL update is issued.

Source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java:369

        JdbcUtil.namespaceToString(namespace));
  }

  @Override
  public void renameTable(TableIdentifier from, TableIdentifier to) {
    if (from.equals(to)) {
      return;
    }

    if (!tableExists(from)) {
      throw new NoSuchTableException("Table does not exist: %s", from);
    }

    if (!namespaceExists(to.namespace())) {
      throw new NoSuchNamespaceException("Namespace does not exist: %s", to.namespace());
    }

    if (schemaVersion == JdbcUtil.SchemaVersion.V1 && viewExists(to)) {
      throw new AlreadyExistsException("Cannot rename %s to %s. View already exists", from, to);
    }

    if (tableExists(to)) {
      throw new AlreadyExistsException("Table already exists: %s", to);
    }

    int updatedRecords =
        execute(
            err -> {
              if (JdbcUtil.isConstraintViolation(err)) {
                throw new AlreadyExistsException("Table already exists: %s", to);
              }
            },
            (schemaVersion == JdbcUtil.SchemaVersion.V1)
                ? JdbcUtil.V1_RENAME_TABLE_SQL
                : JdbcUtil.V0_RENAME_TABLE_SQL,
            JdbcUtil.namespaceToString(to.namespace()),
            to.name(),

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Choose a different target TableIdentifier that does not collide with an existing view
  2. Drop or rename the existing view at the target name first, then retry renameTable
  3. If view/table sharing a name is intended, migrate the catalog to the V0 (shared-identifier) schema version where this check is not applied

Example fix

// before
catalog.renameTable(from, TableIdentifier.of(ns, "report")); // fails: view 'report' exists
// after
if (!catalog.listViews(ns).contains(TableIdentifier.of(ns, "report"))) {
  catalog.renameTable(from, TableIdentifier.of(ns, "report"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (catalog instanceof JdbcCatalog && catalog.listViews(to.namespace()).contains(to)) { throw new IllegalStateException("target collides with view"); }

Type guard

boolean targetIsFree = !catalog.tableExists(to) && !catalog.listViews(to.namespace()).contains(to);

Try / catch

try { catalog.renameTable(from, to); } catch (AlreadyExistsException e) { /* pick a new target name or drop the view */ }

Prevention

When it happens

Trigger: Calling catalog.renameTable(from, to) where 'to' names an existing view and the JDBC catalog schemaVersion is V1 (V1_RENAME_TABLE_SQL used, catalog_property 'catalog-table'/'catalog-view' separated).

Common situations: Migrating catalogs where a view was created at the target name; upgrading or downgrading JDBC schema versions where V1 separated views and tables but identifiers still overlap; concurrent creation of a view between the caller's exists-check and rename.

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/31a40ac2001ff641. Report an issue: GitHub.