{"record":{"id":"144f394c5207bc0c","repo":"apache/iceberg","slug":"failed-to-create-table-s-in-catalog-s","errorCode":null,"errorMessage":"Failed to create table %s in catalog %s","messagePattern":"Failed to create table (.+?) in catalog (.+?)","errorType":"exception","errorClass":"CommitFailedException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/jdbc/JdbcTableOperations.java","lineNumber":195,"sourceCode":"    }\n\n    if (JdbcUtil.tableExists(schemaVersion, catalogName, connections, tableIdentifier)) {\n      throw new AlreadyExistsException(\"Table already exists: %s\", tableIdentifier);\n    }\n\n    int insertRecord =\n        JdbcUtil.doCommitCreateTable(\n            schemaVersion,\n            connections,\n            catalogName,\n            namespace,\n            tableIdentifier,\n            newMetadataLocation);\n\n    if (insertRecord == 1) {\n      LOG.debug(\"Successfully committed to new table: {}\", tableIdentifier);\n    } else {\n      throw new CommitFailedException(\n          \"Failed to create table %s in catalog %s\", tableIdentifier, catalogName);\n    }\n  }\n\n  private void validateMetadataLocation(Map<String, String> table, TableMetadata base) {\n    String catalogMetadataLocation = table.get(METADATA_LOCATION_PROP);\n    String baseMetadataLocation = base != null ? base.metadataFileLocation() : null;\n\n    if (!Objects.equals(baseMetadataLocation, catalogMetadataLocation)) {\n      throw new CommitFailedException(\n          \"Cannot commit %s: metadata location %s has changed from %s\",\n          tableIdentifier, baseMetadataLocation, catalogMetadataLocation);\n    }\n  }\n\n  @Override\n  public FileIO io() {\n    return fileIO;","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/jdbc/JdbcTableOperations.java#L177-L213","documentation":"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.","triggerScenarios":"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().","commonSituations":"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).","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"],"exampleFix":"// before\ncatalog.createTable(ident, schema); // rare CommitFailedException aborts pipeline\n// after\ntry {\n  catalog.createTable(ident, schema);\n} catch (CommitFailedException e) {\n  if (!catalog.tableExists(ident)) {\n    catalog.createTable(ident, schema); // retry once; else someone else created it\n  }\n}","handlingStrategy":"retry","validationCode":"if (!catalog.tableExists(identifier)) { /* safe window is small; still retry on failure */ }","typeGuard":null,"tryCatchPattern":"try { catalog.createTable(identifier, schema); } catch (CommitFailedException e) { if (!catalog.tableExists(identifier)) { catalog.createTable(identifier, schema); } }","preventionTips":["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"],"tags":["jdbc","commit-retry","concurrency","catalog-commit"],"backgroundTag":"database-write-failed","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"}