{"record":{"id":"e210091f6b0dc67d","repo":"apache/iceberg","slug":"cannot-rename-s-to-s-table-already-exists-e21009","errorCode":null,"errorMessage":"Cannot rename %s to %s. Table already exists","messagePattern":"Cannot rename (.+?) to (.+?)\\. Table already exists","errorType":"exception","errorClass":"AlreadyExistsException","httpStatus":409,"severity":"error","filePath":"nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java","lineNumber":521,"sourceCode":"      // to catch all kinds of network errors (e.g. connection reset). Network code implementation\n      // details and all kinds of network devices can induce unexpected behavior. So better be\n      // safe than sorry.\n      throw new CommitStateUnknownException(ex);\n    }\n    // Intentionally just \"throw through\" Nessie's HttpClientException here and do not \"special\n    // case\"\n    // just the \"timeout\" variant to propagate all kinds of network errors (e.g. connection reset).\n    // Network code implementation details and all kinds of network devices can induce unexpected\n    // behavior. So better be safe than sorry.\n  }\n\n  private static void validateToContentForRename(\n      TableIdentifier from, TableIdentifier to, IcebergContent existingToContent) {\n    if (existingToContent != null) {\n      if (existingToContent.getType() == Content.Type.ICEBERG_VIEW) {\n        throw new AlreadyExistsException(\"Cannot rename %s to %s. View already exists\", from, to);\n      } else if (existingToContent.getType() == Content.Type.ICEBERG_TABLE) {\n        throw new AlreadyExistsException(\"Cannot rename %s to %s. Table already exists\", from, to);\n      } else {\n        throw new AlreadyExistsException(\n            \"Cannot rename %s to %s. Another content of type %s with same name already exists\",\n            from, to, existingToContent.getType());\n      }\n    }\n  }\n\n  private static void validateFromContentForRename(\n      TableIdentifier from, Content.Type type, IcebergContent existingFromContent) {\n    if (existingFromContent == null) {\n      if (type == Content.Type.ICEBERG_VIEW) {\n        throw new NoSuchViewException(\"View does not exist: %s\", from);\n      } else if (type == Content.Type.ICEBERG_TABLE) {\n        throw new NoSuchTableException(\"Table does not exist: %s\", from);\n      } else {\n        throw new RuntimeException(\"Cannot perform rename for content type: \" + type);\n      }","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java#L503-L539","documentation":"Same guard as the view case: validateToContentForRename throws AlreadyExistsException when the rename destination already contains content of type ICEBERG_TABLE. The rename is rejected so an existing table is never clobbered by a Put of other content.","triggerScenarios":"catalog.renameTable(from, to) where 'to' is an existing table, or catalog.renameView(from, to) where 'to' names an existing table — fetchContent(to) returns non-null content typed ICEBERG_TABLE.","commonSituations":"Copy/paste of rename scripts with stale destination names; re-running a migration that already created the destination table; schema-drift tools recreating a table at the target name between planning and execution.","solutions":["Drop or rename the existing destination table first, then rerun the rename.","Use a fresh destination identifier after checking catalog.tableExists(to) returns false.","Make migration scripts idempotent: skip the rename if the destination already exists and matches expectations.","If an unintended duplicate exists, inspect Nessie content listing for the namespace to clean up the collision."],"exampleFix":"// before\ncatalog.renameView(v1, TableIdentifier.of(\"ns\",\"report\")); // table 'ns.report' exists\n// after\nTableIdentifier dest = TableIdentifier.of(\"ns\",\"report\");\nif (!catalog.tableExists(dest)) {\n  catalog.renameView(v1, dest);\n}","handlingStrategy":"validation","validationCode":"if (catalog.tableExists(to) || catalog.namespaceExists(...)) { /* pick new name */ }\n// minimal check:\nboolean destFree = !catalog.tableExists(to);\nif (!destFree) { throw new ValidationException(\"table exists at destination: \" + to); }","typeGuard":null,"tryCatchPattern":"try {\n  catalog.renameView(from, to);\n} catch (AlreadyExistsException e) {\n  // destination is an existing table; choose a free identifier\n  to = nextAvailableIdentifier(to);\n  catalog.renameView(from, to);\n}","preventionTips":["Guard renames with catalog.tableExists(destination).","Generate destinations from a fresh listing of the namespace, not hardcoded names.","Re-run idempotent migrations safely by checking destination state first.","Document naming conventions so table/view identifiers never overlap."],"tags":["nessie","catalog","rename","already-exists","table"],"backgroundTag":"file-already-exists","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}