apache/iceberg · error · AlreadyExistsException
Table already exists: %s
Error message
Table already exists: %s
What it means
AlreadyExistsException from BigQueryMetastoreClientImpl.internalCreate when the BigQuery tables.insert reports the table already exists. The original AlreadyExistsException is chained as the cause and the message includes the full Table object.
Source
Thrown at bigquery/src/main/java/org/apache/iceberg/gcp/bigquery/BigQueryMetastoreClientImpl.java:363
return response;
}
private Table internalCreate(Table table) {
try {
HttpResponse response =
client
.tables()
.insert(
Preconditions.checkNotNull(table.getTableReference()).getProjectId(),
Preconditions.checkNotNull(table.getTableReference()).getDatasetId(),
table)
.executeUnparsed();
return convertExceptionIfUnsuccessful(response).parseAs(Table.class);
} catch (IOException e) {
throw new RuntimeIOException("%s", e);
} catch (AlreadyExistsException e) {
throw new AlreadyExistsException(e, "Table already exists: %s", table);
}
}
@Override
public Table load(TableReference tableReference) {
try {
HttpResponse response =
client
.tables()
.get(
tableReference.getProjectId(),
tableReference.getDatasetId(),
tableReference.getTableId())
.executeUnparsed();
if (response.getStatusCode() == HttpStatusCodes.STATUS_CODE_NOT_FOUND) {
throw new NoSuchTableException("%s", response.getStatusMessage());
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check tableExists(identifier) before creating, or use catalog.createOrReplaceTable when replacement is intended
- Catch AlreadyExistsException and treat as success for idempotent setup
- Add randomness/locking for concurrent creators of the same table name
- Verify you are targeting the intended dataset/project (name collision across environments)
Example fix
// before
catalog.createTable(ident, schema);
// after
if (!catalog.tableExists(ident)) {
catalog.createTable(ident, schema);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!catalog.tableExists(ident)) { catalog.createTable(ident, schema); } Try / catch
try { catalog.createTable(ident, schema); } catch (AlreadyExistsException e) { /* exists; skip or replace */ } Prevention
- Use createOrReplaceTable when replacement is intended
- Serialize table creation across concurrent jobs
- Verify target dataset/project to avoid name collisions
When it happens
Trigger: Calling catalog.createTable / client.create for a TableIdentifier whose table already exists in the dataset; concurrent createTable races for the same identifier; createOrReplace fallback that catches this to switch to replace.
Common situations: CREATE TABLE without IF NOT EXISTS semantics in scripts, two Spark jobs creating the same table concurrently, rerunning schema-initialization jobs.
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
- Namespace already exists: %s
- Table already exists: %s
- Table with same name already exists: %s
- Cannot create namespace %s: already exists
- Table already exists: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/78b5728bd46caf0e.
Report an issue: GitHub.