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

validateToContentForRename refuses a rename when the destination identifier already holds content of type ICEBERG_VIEW. renameTable/renameView first fetch the destination's existing content and throw Iceberg's AlreadyExistsException to prevent silently overwriting a view.

Source

Thrown at nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java:519

    } catch (HttpClientException ex) {
      // Intentionally catch all nessie-client-exceptions here and not just the "timeout" variant
      // to catch all kinds of network errors (e.g. connection reset). Network code implementation
      // details and all kinds of network devices can induce unexpected behavior. So better be
      // safe than sorry.
      throw new CommitStateUnknownException(ex);
    }
    // Intentionally just "throw through" Nessie's HttpClientException here and do not "special
    // case"
    // just the "timeout" variant to propagate all kinds of network errors (e.g. connection reset).
    // Network code implementation details and all kinds of network devices can induce unexpected
    // behavior. So better be safe than sorry.
  }

  private static void validateToContentForRename(
      TableIdentifier from, TableIdentifier to, IcebergContent existingToContent) {
    if (existingToContent != null) {
      if (existingToContent.getType() == Content.Type.ICEBERG_VIEW) {
        throw new AlreadyExistsException("Cannot rename %s to %s. View already exists", from, to);
      } else if (existingToContent.getType() == Content.Type.ICEBERG_TABLE) {
        throw new AlreadyExistsException("Cannot rename %s to %s. Table already exists", from, to);
      } else {
        throw new AlreadyExistsException(
            "Cannot rename %s to %s. Another content of type %s with same name already exists",
            from, to, existingToContent.getType());
      }
    }
  }

  private static void validateFromContentForRename(
      TableIdentifier from, Content.Type type, IcebergContent existingFromContent) {
    if (existingFromContent == null) {
      if (type == Content.Type.ICEBERG_VIEW) {
        throw new NoSuchViewException("View does not exist: %s", from);
      } else if (type == Content.Type.ICEBERG_TABLE) {
        throw new NoSuchTableException("Table does not exist: %s", from);
      } else {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Drop or rename the existing view at the destination first, then rerun the rename.
  2. Choose a different destination identifier that is not in use (check with tableExists/namespace listing).
  3. If the view should be replaced intentionally, drop it explicitly rather than relying on rename to overwrite.
  4. Check whether identifier case sensitivity (support-case-sensitive-paths / quoting) makes you collide with an unexpected existing view.

Example fix

// before
catalog.renameTable(TableIdentifier.of("ns","events"), TableIdentifier.of("ns","events_view")); // view exists there
// after
if (catalog.tableExists(TableIdentifier.of("ns","events_view")) || viewExists(catalog, "ns.events_view")) {
  catalog.dropTable(TableIdentifier.of("ns","events_view"));
}
catalog.renameTable(TableIdentifier.of("ns","events"), TableIdentifier.of("ns","events_view"));
Defensive patterns

Strategy: validation

Validate before calling

// listNamespaces + table/view checks before renaming
boolean destFree = !catalog.tableExists(to) && !viewExists(catalog, to);
if (!destFree) { throw new ValidationException("destination in use: " + to); }

Try / catch

try {
  catalog.renameTable(from, to);
} catch (AlreadyExistsException e) {
  LOGGER.error("destination {} already exists ({})", to, e.getMessage());
  // pick another destination or drop explicitly
}

Prevention

When it happens

Trigger: catalog.renameTable(from, to) where 'to' names an existing view, or catalog.renameView(from, to) where 'to' names an existing view — fetchContent(to) returns a non-null IcebergContent with type ICEBERG_VIEW.

Common situations: Naming collision between table and view namespaces in mixed Spark/Iceberg setups; recreating a pipeline that previously created a view at the target name; case-sensitivity confusion producing seemingly 'new' names that actually match existing 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/04e53d06d2324910. Report an issue: GitHub.