apache/iceberg · error · AlreadyExistsException

Cannot rename %s to %s. Table already exists

Error message

Cannot rename %s to %s. Table already exists

What it means

JdbcCatalog.renameView throws AlreadyExistsException when the destination identifier collides with an existing TABLE. Views and tables share the identifier space in this catalog, so a view cannot be renamed onto an existing table name.

Source

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

  public void renameView(TableIdentifier from, TableIdentifier to) {
    if (schemaVersion != JdbcUtil.SchemaVersion.V1) {
      throw new UnsupportedOperationException(VIEW_WARNING_LOG_MESSAGE);
    }

    if (from.equals(to)) {
      return;
    }

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

    if (!viewExists(from)) {
      throw new NoSuchViewException("View does not exist");
    }

    if (tableExists(to)) {
      throw new AlreadyExistsException("Cannot rename %s to %s. Table already exists", from, to);
    }

    if (viewExists(to)) {
      throw new AlreadyExistsException("Cannot rename %s to %s. View already exists", from, to);
    }

    int updatedRecords =
        execute(
            err -> {
              if (JdbcUtil.isConstraintViolation(err)) {
                throw new AlreadyExistsException(
                    "Cannot rename %s to %s. View already exists", from, to);
              }
            },
            JdbcUtil.RENAME_VIEW_SQL,
            JdbcUtil.namespaceToString(to.namespace()),
            to.name(),
            catalogName,

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Choose a different destination name that does not collide with existing tables.
  2. Check catalog.tableExists(to) before renaming and pick an alternate name if taken.
  3. Drop the conflicting table first if it is truly obsolete (destructive — confirm first).
  4. Catch AlreadyExistsException and surface a clear conflict to the user.

Example fix

// before
catalog.renameView(from, to); // fails if a table named 'to' exists

// after
if (catalog.tableExists(to)) {
  throw new IllegalStateException("Target name in use by a table: " + to);
}
catalog.renameView(from, to);
Defensive patterns

Strategy: validation

Validate before calling

if (catalog.tableExists(to)) {
  throw new IllegalArgumentException("Target name taken by table: " + to);
}
catalog.renameView(from, to);

Try / catch

try {
  catalog.renameView(from, to);
} catch (AlreadyExistsException e) {
  // pick another destination name or surface conflict
}

Prevention

When it happens

Trigger: Calling catalog.renameView(from, to) where tableExists(to) is true — the target name is already taken by a table in the same namespace.

Common situations: Reusing a name that was previously a table, migrating tables to views (or vice versa) without cleaning up, generating target names programmatically that collide.

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