prestodb/presto · error · PrestoException
ICEBERG_INVALID_FORMAT_VERSION
ICEBERG_INVALID_FORMAT_VERSION
Error message
Iceberg table updates require at least format version 2 and update mode must be merge-on-read
What it means
Thrown when a row-level update targets an Iceberg table that either has format version below 2 (no delete files) or is not configured with update.mode=merge-on-read. Row-level DML requires v2 semantics and merge-on-read mode in this connector.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java:939
public ConnectorMergeTableHandle beginMerge(ConnectorSession session, ConnectorTableHandle tableHandle)
{
shouldRunInAutoCommitTransaction("MERGE INTO");
IcebergTableHandle icebergTableHandle = (IcebergTableHandle) tableHandle;
verify(icebergTableHandle.getIcebergTableName().getTableType() == DATA, "only the data table can have data merged");
Table icebergTable = getIcebergTable(session, icebergTableHandle.getSchemaTableName());
validateBranchExists(icebergTableHandle, icebergTable);
int formatVersion = ((BaseTable) icebergTable).operations().current().formatVersion();
if (formatVersion > MAX_FORMAT_VERSION_FOR_ROW_LEVEL_OPERATIONS) {
throw new PrestoException(NOT_SUPPORTED,
format("Iceberg table updates for format version %s are not supported yet", formatVersion));
}
if (formatVersion < MIN_FORMAT_VERSION_FOR_DELETE ||
!Optional.ofNullable(icebergTable.properties().get(TableProperties.UPDATE_MODE))
.map(mode -> mode.equals(MERGE_ON_READ.modeName()))
.orElse(false)) {
throw new PrestoException(ICEBERG_INVALID_FORMAT_VERSION,
"Iceberg table updates require at least format version 2 and update mode must be merge-on-read");
}
validateTableMode(session, icebergTable);
IcebergInsertTableHandle insertHandle = new IcebergInsertTableHandle(
icebergTableHandle.getSchemaName(),
icebergTableHandle.getIcebergTableName(),
toPrestoSchema(icebergTable.schema(), typeManager),
toPrestoPartitionSpec(icebergTable.spec(), typeManager),
getColumns(icebergTable.schema(), icebergTable.spec(), typeManager),
icebergTable.location(),
getFileFormat(icebergTable),
getCompressionCodec(session),
icebergTable.properties(),
getSupportedSortFields(icebergTable.schema(), icebergTable.sortOrder()),
Optional.empty());
Map<Integer, PrestoIcebergPartitionSpec> partitionSpecs = transformValues(icebergTable.specs(), partitionSpec -> toPrestoPartitionSpec(partitionSpec, typeManager));View on GitHub (pinned to 55bb57d202)
Solutions
- Set the table property update.mode=merge-on-read, e.g. ALTER TABLE ... SET TBLPROPERTIES ('update.mode'='merge-on-read').
- Upgrade the table to format version 2 (rewrite the table or set format-version via a supported writer).
- Recreate the table with format-version=2 and merge-on-read mode before running row-level DML.
Example fix
// before
MERGE INTO t ...; -- t is format version 1 / copy-on-write
// after
ALTER TABLE t SET TBLPROPERTIES ('update.mode' = 'merge-on-read', 'format-version' = '2');
MERGE INTO t ...; Defensive patterns
Strategy: validation
Validate before calling
-- verify format version and update mode before MERGE/UPDATE/DELETE
SELECT key, value FROM "t$properties" WHERE key IN ('format-version', 'update.mode');
-- proceed only if format-version >= 2 and update.mode = merge-on-read Try / catch
try { merge(...); }
catch (PrestoException e) { if (ICEBERG_INVALID_FORMAT_VERSION.equals(e.getErrorCode())) { /* set table properties and retry */ } } Prevention
- Create Iceberg tables with format-version=2 by default
- Set update.mode=merge-on-read on tables used for DML
- Audit table properties after migrations between engines
When it happens
Trigger: Running MERGE/UPDATE/DELETE against a format-version-1 table, or a v2 table whose table property update.mode is not set to merge-on-read (e.g. copy-on-write).
Common situations: Legacy tables created before the engine supported v2; tables created with copy-on-write defaults; properties changed or never set after upgrading Presto.
Related errors
- ICEBERG_INCOMPATIBLE_VERSION
- INVALID_TABLE_PROPERTY
- INVALID_TABLE_PROPERTY
- Invalid value [%s]. Valid values: %s
- HIVE_INVALID_ENCRYPTION_METADATA
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/a87db10809284ba4.
Report an issue: GitHub.