prestodb/presto · warning · CommitFailedException
Metadata location [%s] is not same as table metadata locatio
Error message
Metadata location [%s] is not same as table metadata location [%s] for %s
What it means
HiveTableOperations.commit() performs optimistic concurrency: before writing new Iceberg metadata it compares the METADATA_LOCATION parameter it read earlier against the current value in the Hive Metastore. If they differ, another process committed to the table in between, and this CommitFailedException aborts the write so Iceberg can retry with fresh state.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/HiveTableOperations.java:282
parameters.put(TABLE_COMMENT, tableComment);
}
Table.Builder builder = Table.builder()
.setDatabaseName(database)
.setTableName(tableName)
.setOwner(owner.orElseThrow(() -> new IllegalStateException("Owner not set")))
.setTableType(PrestoTableType.EXTERNAL_TABLE)
.setDataColumns(toHiveColumns(metadata.schema().columns()))
.withStorage(storage -> storage.setLocation(metadata.location()))
.withStorage(storage -> storage.setStorageFormat(STORAGE_FORMAT))
.setParameters(parameters);
table = builder.build();
}
else {
Table currentTable = getTable();
checkState(currentMetadataLocation != null, "No current metadata location for existing table");
String metadataLocation = currentTable.getParameters().get(METADATA_LOCATION);
if (!currentMetadataLocation.equals(metadataLocation)) {
throw new CommitFailedException("Metadata location [%s] is not same as table metadata location [%s] for %s", currentMetadataLocation, metadataLocation, getSchemaTableName());
}
table = Table.builder(currentTable)
.setDataColumns(toHiveColumns(metadata.schema().columns()))
.withStorage(storage -> storage.setLocation(metadata.location()))
.setParameter(METADATA_LOCATION, newMetadataLocation)
.setParameter(PREVIOUS_METADATA_LOCATION, currentMetadataLocation)
.build();
}
}
catch (RuntimeException e) {
try {
io().deleteFile(newMetadataLocation);
}
catch (RuntimeException exception) {
e.addSuppressed(exception);
}
throw e;
}View on GitHub (pinned to 55bb57d202)
Solutions
- Retry the operation: re-read the table (refresh) so the new base metadata location is picked up, then re-apply the change.
- Ensure only one writer path modifies the table (disable conflicting maintenance jobs or coordinate schedules).
- If using an external commit lock, verify lock configuration so concurrent commits are serialized.
- Upgrade Iceberg/Hive connectors if retry loops fail repeatedly due to known commit races.
Example fix
// before Table table = loadTable(session, tableName); // loaded long ago transaction(table).updateSchema(...).commit(); // after Table table = loadTable(session, tableName); table.refresh(); // re-read latest metadata before committing transaction(table).updateSchema(...).commit();
Defensive patterns
Strategy: retry
Validate before calling
Table t = loadTable(...); t.refresh(); // confirm METADATA_LOCATION unchanged before a long-running commit
Try / catch
try { table.newAppend().appendFile(f).commit(); }
catch (CommitFailedException e) { table.refresh(); /* retry write once or twice */ } Prevention
- Always refresh the table right before committing.
- Avoid multiple writers without a commit lock.
- Keep write transactions short to reduce race windows.
When it happens
Trigger: Calling commit() (e.g. via table.refresh() + new snapshot, schema change, or Iceberg DDL) while the METADATA_LOCATION property in HMS no longer equals the baseMetadataLocation captured when the operation started.
Common situations: Two writers (different Presto clusters, Spark, Flink, or a compaction/maintenance job) committing to the same Iceberg table concurrently; long-running queries whose commit phase races with another commit; stale table handle reused after another commit.
Related errors
- The table %s.%s has been modified concurrently
- 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/5f7e69a3dc8ba77f.
Report an issue: GitHub.