apache/iceberg · error · AlreadyExistsException

Table already exists: %s

Error message

Table already exists: %s

What it means

CatalogHandlers.stageTableCreate rejects a create-table request with AlreadyExistsException when a table with the same identifier already exists (catalog.tableExists check). Staged creates refuse to clobber existing tables; this maps to a 409-style conflict in REST semantics.

Source

Thrown at core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java:412

  }

  public static ListTablesResponse listTables(
      Catalog catalog, Namespace namespace, String pageToken, String pageSize) {
    List<TableIdentifier> results = catalog.listTables(namespace);

    Pair<List<TableIdentifier>, String> page =
        paginate(results, pageToken, Integer.parseInt(pageSize));

    return ListTablesResponse.builder().addAll(page.first()).nextPageToken(page.second()).build();
  }

  public static LoadTableResponse stageTableCreate(
      Catalog catalog, Namespace namespace, CreateTableRequest request) {
    request.validate();

    TableIdentifier ident = TableIdentifier.of(namespace, request.name());
    if (catalog.tableExists(ident)) {
      throw new AlreadyExistsException("Table already exists: %s", ident);
    }

    Map<String, String> properties = Maps.newHashMap();
    properties.put("created-at", OffsetDateTime.now(ZoneOffset.UTC).toString());
    properties.putAll(request.properties());

    String location;
    if (request.location() != null) {
      location = request.location();
    } else {
      location =
          catalog
              .buildTable(ident, request.schema())
              .withPartitionSpec(request.spec())
              .withSortOrder(request.writeOrder())
              .withProperties(properties)
              .createTransaction()
              .table()

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check tableExists before creating, or catch AlreadyExistsException and reuse the table
  2. Use create-or-replace / create-or-ignore transaction semantics if intended
  3. Use unique (timestamped/suffixed) table names for repeated pipelines
  4. Find the duplicate request source (retries, schedulers) causing double creates

Example fix

// before
Table t = catalog.createTable(ident, schema); // throws if exists
// after
Table t = catalog.tableExists(ident)
    ? catalog.loadTable(ident)
    : catalog.createTable(ident, schema);
Defensive patterns

Strategy: try-catch

Validate before calling

if (catalog.tableExists(ident)) {
  // load or skip
} else {
  catalog.createTable(ident, schema);
}

Try / catch

try {
  catalog.createTable(ident, schema);
} catch (AlreadyExistsException e) {
  table = catalog.loadTable(ident);
}

Prevention

When it happens

Trigger: Calling createTable/stageTableCreate (REST POST v1/namespaces/{ns}/tables) when a table with namespace + request.name() already exists.

Common situations: Retried requests after a first successful create; concurrent jobs creating the same table; re-running setup scripts without create-or-replace semantics.

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