apache/iceberg · error · AlreadyExistsException

Table %s already exists in the database %s and catalog %s

Error message

Table %s already exists in the database %s and catalog %s

What it means

FlinkDynamicTableFactory auto-creates the Iceberg table (ignoreIfExists=true) if it doesn't exist; if createIcebergTable still reports TableAlreadyExistException, it is rethrown as AlreadyExistsException with this message — a concurrent-creation race between existence check and create.

Source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/FlinkDynamicTableFactory.java:226

    if (!flinkCatalog.databaseExists(catalogDatabase)) {
      try {
        flinkCatalog.createDatabase(
            catalogDatabase, new CatalogDatabaseImpl(Maps.newHashMap(), null), true);
      } catch (DatabaseAlreadyExistException e) {
        throw new AlreadyExistsException(
            e,
            "Database %s already exists in the iceberg catalog %s.",
            catalogName,
            catalogDatabase);
      }
    }

    // Create table if not exists in the external catalog.
    if (!flinkCatalog.tableExists(objectPath)) {
      try {
        flinkCatalog.createIcebergTable(objectPath, resolvedCatalogTable, true);
      } catch (TableAlreadyExistException e) {
        throw new AlreadyExistsException(
            e,
            "Table %s already exists in the database %s and catalog %s",
            catalogTable,
            catalogDatabase,
            catalogName);
      }
    }

    return TableLoader.fromCatalog(
        flinkCatalog.getCatalogLoader(), TableIdentifier.of(catalogDatabase, catalogTable));
  }

  /**
   * Merges source catalog properties (catalog name, database, table) with connector properties.
   * Source catalog name, database, table are serialized as json in FlinkCatalog#getTable to be able
   * to isolate them from iceberg table props, Here, we flatten and merge them back.
   *
   * @param tableProps the existing table properties

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Retry loading the table; it now exists
  2. Sequence table creation before launching parallel jobs
  3. Catch the AlreadyExistsException and treat the table as existing, proceeding with reads/writes

Example fix

// before
flinkCatalog.createIcebergTable(objectPath, resolvedCatalogTable, true);
// after
try {
  flinkCatalog.createIcebergTable(objectPath, resolvedCatalogTable, true);
} catch (AlreadyExistsException e) {
  // created concurrently; proceed with existing table
}
Defensive patterns

Strategy: retry

Validate before calling

if (catalog.tableExists(objectPath)) { /* skip creation */ }

Try / catch

try { loader.open(); } catch (AlreadyExistsException e) { /* table created concurrently; proceed with existing */ }

Prevention

When it happens

Trigger: createTableLoader: tableExists returns false, then another job creates the same table before createIcebergTable completes.

Common situations: Parallel job startup against a shared catalog where multiple workers materialize the same sink table.

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