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

InMemoryCatalog.renameTable throws AlreadyExistsException when a view already exists at the destination identifier. The catalog keeps tables and views in separate maps but both occupy the same identifier space, so a rename cannot target an identifier held by a view.

Source

Thrown at core/src/main/java/org/apache/iceberg/inmemory/InMemoryCatalog.java:186

    }

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

      String fromLocation = tables.get(from);
      if (null == fromLocation) {
        throw new NoSuchTableException("Cannot rename %s to %s. Table does not exist", from, to);
      }

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

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

      tables.put(to, fromLocation);
      tables.remove(from);
    }
  }

  @Override
  public void createNamespace(Namespace namespace) {
    createNamespace(namespace, Collections.emptyMap());
  }

  @Override
  public void createNamespace(Namespace namespace, Map<String, String> metadata) {
    synchronized (this) {
      if (namespaceExists(namespace)) {
        throw new AlreadyExistsException(
            "Cannot create namespace %s. Namespace already exists", namespace);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Drop the existing view at the destination before renaming
  2. Pick a destination identifier not used by any view
  3. Check for view existence (e.g. via view catalog APIs) before the rename
  4. Catch AlreadyExistsException and resolve the collision explicitly

Example fix

// before
catalog.renameTable(from, to); // to is a view name
// after
if (catalog.viewExists(to)) {
  catalog.dropView(to);
}
catalog.renameTable(from, to);
Defensive patterns

Strategy: validation

Validate before calling

if (catalog.tableExists(to) || catalog.viewExists(to)) { throw new IllegalStateException("Destination occupied: " + to); }

Try / catch

try { catalog.renameTable(from, to); } catch (AlreadyExistsException e) { if (catalog.viewExists(to)) { catalog.dropView(to); catalog.renameTable(from, to); } }

Prevention

When it happens

Trigger: Calling catalog.renameTable(from, to) where views contains 'to'. E.g. renaming a table to a name that a view already occupies in the same namespace.

Common situations: Environments where views and tables share naming conventions; scripts unaware a view was created at the target name; migrating tables into namespaces occupied by reporting views.

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