apache/iceberg · warning · CommitFailedException
Cannot commit to table
Error message
Cannot commit to table %s metadata location from %s to %s because it has been concurrently modified to %s
What it means
This is the optimistic-concurrency conflict of the in-memory catalog: the commit expected the table's metadata location to equal oldLocation, but the map holds a different existingLocation, meaning another committer advanced the table in between. Per Iceberg's commit contract, CommitFailedException signals the caller to refresh and retry the update against the new state.
Solutions
- Retry the commit: catch CommitFailedException, call table.refresh(), re-apply the update, and commit again (Iceberg's RetryUtil/Tasks.foreach with retry works well).
- Reduce conflict windows by shortening transaction scopes or partitioning work across distinct tables.
- Ensure every retry reloads/refreshes metadata; never reuse stale TableMetadata.
Example fix
// before
table.updateSchema().addColumn("c", Types.IntegerType.get()).commit();
// after
Tasks.foreach(table)
.retry(3)
.onlyOn(CommitFailedException.class)
.run(t -> t.refresh());
table.refresh();
table.updateSchema().addColumn("c", Types.IntegerType.get()).commit(); Defensive patterns
Strategy: retry
Try / catch
try { table.commit(update); } catch (CommitFailedException e) { table.refresh(); /* re-apply update on refreshed metadata and retry, bounded attempts */ } Prevention
- Always refresh() the table before reapplying a failed commit
- Use Tasks.foreach(...).retry(n).onlyOn(CommitFailedException.class) for commits
- Keep transactions short to shrink conflict windows
- Partition concurrent writers across distinct tables/partitions
When it happens
Trigger: Two writers load the same table and both call commit(); the loser sees existingLocation != oldLocation and neither base nor existingLocation is null. Any concurrent metadata operation (schema update, append, partition spec change) on the same table.
Common situations: Multiple executors/threads appending to one table; concurrent schema evolution and writes; retry loops that do not refresh the table before recommitting.
Related errors
- Cannot commit to view
- View was updated concurrently
- Cannot commit: Base metadata location
- Cannot commit changes based on stale table metadata
- Cannot commit file that conflicts with existing partition
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/bc274ee4daac14bd.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/inmemory/InMemoryCatalog.java:454
if (views.containsKey(tableIdentifier)) {
throw new AlreadyExistsException(
"View with same name already exists: %s", tableIdentifier);
}
tables.compute(
tableIdentifier,
(k, existingLocation) -> {
if (!Objects.equal(existingLocation, oldLocation)) {
if (null == base) {
throw new AlreadyExistsException("Table already exists: %s", tableName());
}
if (null == existingLocation) {
throw new NoSuchTableException("Table does not exist: %s", tableName());
}
throw new CommitFailedException(
"Cannot commit to table %s metadata location from %s to %s "
+ "because it has been concurrently modified to %s",
tableIdentifier, oldLocation, newLocation, existingLocation);
}
return newLocation;
});
}
}
@Override
public FileIO io() {
return fileIO;
}
@Override
protected String tableName() {
return fullTableName;
}View on GitHub (pinned to 86d9c8fc54)