apache/iceberg · warning · CommitFailedException
Failed to create table %s in catalog %s
Error message
Failed to create table %s in catalog %s
What it means
After the existence pre-checks pass, createTable performs the INSERT of the new catalog row. If the INSERT affects any number of rows other than 1 (almost always 0), createTable throws CommitFailedException because the table could not be registered. This is another optimistic-concurrency failure point: the INSERT can silently match 0 rows under concurrent modification or DB-specific behaviors.
Source
Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcTableOperations.java:195
}
if (JdbcUtil.tableExists(schemaVersion, catalogName, connections, tableIdentifier)) {
throw new AlreadyExistsException("Table already exists: %s", tableIdentifier);
}
int insertRecord =
JdbcUtil.doCommitCreateTable(
schemaVersion,
connections,
catalogName,
namespace,
tableIdentifier,
newMetadataLocation);
if (insertRecord == 1) {
LOG.debug("Successfully committed to new table: {}", tableIdentifier);
} else {
throw new CommitFailedException(
"Failed to create table %s in catalog %s", tableIdentifier, catalogName);
}
}
private void validateMetadataLocation(Map<String, String> table, TableMetadata base) {
String catalogMetadataLocation = table.get(METADATA_LOCATION_PROP);
String baseMetadataLocation = base != null ? base.metadataFileLocation() : null;
if (!Objects.equals(baseMetadataLocation, catalogMetadataLocation)) {
throw new CommitFailedException(
"Cannot commit %s: metadata location %s has changed from %s",
tableIdentifier, baseMetadataLocation, catalogMetadataLocation);
}
}
@Override
public FileIO io() {
return fileIO;View on GitHub (pinned to 86d9c8fc54)
Solutions
- Retry the whole create: treat CommitFailedException as retryable — recheck tableExists and re-attempt createTable
- Verify connection autocommit settings so INSERT row counts reflect real commits
- Inspect jdbc_tables constraints/triggers that could make the INSERT no-op
- Fall back to loadTable if a concurrent creator won the race and the existing table is acceptable
Example fix
// before
catalog.createTable(ident, schema); // rare CommitFailedException aborts pipeline
// after
try {
catalog.createTable(ident, schema);
} catch (CommitFailedException e) {
if (!catalog.tableExists(ident)) {
catalog.createTable(ident, schema); // retry once; else someone else created it
}
} Defensive patterns
Strategy: retry
Validate before calling
if (!catalog.tableExists(identifier)) { /* safe window is small; still retry on failure */ } Try / catch
try { catalog.createTable(identifier, schema); } catch (CommitFailedException e) { if (!catalog.tableExists(identifier)) { catalog.createTable(identifier, schema); } } Prevention
- Retry createTable on CommitFailedException after rechecking existence
- Verify connection pool autocommit so INSERT row counts are accurate
- Audit DB triggers/constraints that can suppress the insert
- Avoid heavy create/drop churn on the same table names
When it happens
Trigger: Concurrent drop of the just-validated table before INSERT; DB triggers/policies suppressing the insert; connection in a failed transaction state so the UPDATE/INSERT count reports 0; a race where another creator inserted between tableExists() and doCommitCreateTable().
Common situations: Very high create/delete churn on the same names; autocommit misconfiguration in the connection pool; DB-level constraints beyond the unique key (e.g. foreign key to namespaces in strict setups).
Related errors
- Interrupted during commit
- Failed to update table %s from catalog %s
- Interrupted in call to initialize
- Interrupted in SQL command
- Interrupted in SQL query
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/144f394c5207bc0c.
Report an issue: GitHub.