apache/iceberg · error · CommitFailedException
The table %s.%s has been modified concurrently
Error message
The table %s.%s has been modified concurrently
What it means
HMS reported the table was already modified (e.g. InvalidOperationException from a failed alter), and before declaring failure doCommit re-checks the commit status in strict mode by comparing the stored metadata_location with the new one. If the check confirms the location does not match this commit, a CommitFailedException 'modified concurrently' is thrown — the commit did not land because another writer changed the table first.
Source
Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HiveTableOperations.java:393
+ "table 'HIVE_LOCKS' does not exist. This can occur when using an embedded metastore which does not "
+ "support transactions. To fix this use an alternative metastore.",
e);
}
commitStatus = BaseMetastoreOperations.CommitStatus.UNKNOWN;
if (e.getMessage() != null
&& e.getMessage()
.contains(
"The table has been modified. The parameter value for key '"
+ HiveTableOperations.METADATA_LOCATION_PROP
+ "' is")) {
// It's possible the HMS client incorrectly retries a successful operation, due to network
// issue for example, and triggers this exception. So we need double-check to make sure
// this is really a concurrent modification. Hitting this exception means no pending
// requests, if any, can succeed later, so it's safe to check status in strict mode
commitStatus = checkCommitStatusStrict(newMetadataLocation, tableMetadata);
if (commitStatus == BaseMetastoreOperations.CommitStatus.FAILURE) {
throw new CommitFailedException(
e, "The table %s.%s has been modified concurrently", database, tableName);
}
} else {
LOG.error(
"Cannot tell if commit to {}.{} succeeded, attempting to reconnect and check.",
database,
tableName,
e);
commitStatus = checkCommitStatus(newMetadataLocation, tableMetadata);
}
switch (commitStatus) {
case SUCCESS:
break;
case FAILURE:
throw e;
case UNKNOWN:
throw new CommitStateUnknownException(e);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Retry the whole operation with refreshed table metadata (CommitFailedException is retriable)
- Enable Hive lock acquisition so concurrent committers are serialized
- Inspect table history/metadata_location to identify the competing writer
- Move to a catalog with stronger commit semantics if contention is frequent
Example fix
// before
table.newOverwrite().deleteFile(f).commit(); // may fail under concurrency
// after
RetryUtil.retry(CommitFailedException.class, 3, () -> {
table.refresh();
table.newOverwrite().deleteFile(f).commit();
}); Defensive patterns
Strategy: retry
Validate before calling
String loc = hmsClient.getTable(db, tbl).getParameters().get("metadata_location");
if (!Objects.equals(loc, expectedBaseLocation)) table.refresh(); Try / catch
try {
table.newAppend().appendFile(f).commit();
} catch (CommitFailedException e) {
table.refresh();
// retry with backoff, bounded attempts
} Prevention
- Retry CommitFailedException with fresh metadata and backoff
- Enable Hive locking to serialize committers
- Minimize concurrent writers per table
- Audit which jobs write to shared tables
When it happens
Trigger: doCommit's persistTable throws an exception interpreted as concurrent modification (already-moved metadata_location); the subsequent checkCommitStatusStrict finds metadata_location != newMetadataLocation and status FAILURE.
Common situations: Concurrent Iceberg committers via HiveCatalog without sufficient locking; HMS client retry of a successful alter masking real concurrency; two engines (Spark + Flink) writing the same table.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Cannot commit: Base metadata location '%s' is not same as th
- Failed to commit
- Cannot commit changes based on stale table metadata
- Cannot commit %s due to unexpected exception
- Fail to acquire lock %s to commit new metadata at %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/72c037d0cfc3f9bb.
Report an issue: GitHub.