prestodb/presto · warning · CommitFailedException
The table %s.%s has been modified concurrently
Error message
The table %s.%s has been modified concurrently
What it means
commit() failed with an exception (e.g. InterruptedException / MetastoreException) suggesting the table changed concurrently. Before giving up, Presto re-checks whether the new metadata location was actually committed (checkCommitStatusStrict); if not committed (FAILED) it throws CommitFailedException 'The table <db>.<table> has been modified concurrently'.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/HiveTableOperations.java:351
"Failed to acquire locks from metastore because the underlying metastore "
+ "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 commitStatus;
if (e.getMessage() != null
&& e.getMessage()
.contains(
"The table has been modified. The parameter value for key '"
+ 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, metadata);
if (commitStatus == FAILED) {
throw new CommitFailedException(
e, "The table %s.%s has been modified concurrently", database, tableName);
}
}
else {
// Cannot tell if commit to succeeded, attempting to reconnect and check.
commitStatus = checkCommitStatus(newMetadataLocation, metadata);
}
switch (commitStatus) {
case SUCCESS:
break;
case FAILED:
throw e;
case UNKNOWN:
throw new CommitStateUnknownException(e);
}
}
deleteRemovedMetadataFiles(base, metadata);
}View on GitHub (pinned to 55bb57d202)
Solutions
- Retry the whole write after table.refresh() so the commit is based on the latest metadata location.
- Serialize writers: run compaction/optimization jobs and query engines so they don't commit simultaneously.
- Configure a proper commit lock (HMS lock or external lock) to avoid concurrent commits.
- If this appears spuriously, check HMS client retry policy and network stability between Presto and HMS.
Example fix
// before Table table = catalog.loadTable(identifier); table.newAppend().appendFile(dataFile).commit(); // may race // after Table table = catalog.loadTable(identifier); table.refresh(); table.newAppend().appendFile(dataFile).commit(); // retry on CommitFailedException
Defensive patterns
Strategy: retry
Validate before calling
table.refresh(); long expected = ((IcebergTableHandle) handle).getSnapshotId(); // detect concurrent modification before write
Try / catch
try { commit(); }
catch (CommitFailedException e) { table.refresh(); retryWrite(); } Prevention
- Serialize commits with a lock or single-writer policy.
- Refresh before every commit.
- Keep HMS client retries conservative to avoid duplicate commits.
When it happens
Trigger: Concurrent commit to the same Iceberg table where another writer updated METADATA_LOCATION, plus retry/connection quirks from the HMS client (e.g. HMS retrying a failed operation).
Common situations: Multiple engines (Spark, Flink, Presto) or jobs writing the same table simultaneously; network retries from the HMS client causing duplicate commit attempts.
Related errors
- Metadata location [%s] is not same as table metadata locatio
- ICEBERG_COMMIT_ERROR
- ICEBERG_INVALID_METADATA
- Cannot commit: stale table metadata for %s
- HIVE_METASTORE_ERROR
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/f934eabe812fc8c8.
Report an issue: GitHub.