prestodb/presto · error · RuntimeException

Iceberg table updates require at least format version 2 and

Error message

Iceberg table updates require at least format version 2 and update mode must be merge-on-read

What it means

beginUpdate validates row-level update support: the table's Iceberg format version must be exactly 2 with merge-on-read update mode (versions above MAX_FORMAT_VERSION_FOR_ROW_LEVEL_OPERATIONS or copy-on-write are rejected). The check fails when the table's formatVersion is outside the supported range for UPDATE statements.

Source

Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java:1921

    @Override
    public ConnectorTableHandle beginUpdate(ConnectorSession session, ConnectorTableHandle tableHandle, List<ColumnHandle> updatedColumns)
    {
        IcebergTableHandle handle = (IcebergTableHandle) tableHandle;
        Table icebergTable = getIcebergTable(session, handle.getSchemaTableName());
        validateBranchExists(handle, icebergTable);
        int formatVersion = opsFromTable(icebergTable).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 RuntimeException("Iceberg table updates require at least format version 2 and update mode must be merge-on-read");
        }
        validateTableMode(session, icebergTable);
        return handle
                .withUpdatedColumns(updatedColumns.stream()
                        .map(IcebergColumnHandle.class::cast)
                        .collect(toImmutableList()));
    }

    @Override
    public void finishUpdate(ConnectorSession session, ConnectorTableHandle tableHandle, Collection<Slice> fragments)
    {
        IcebergTableHandle handle = (IcebergTableHandle) tableHandle;
        Table icebergTable = getIcebergTable(session, handle.getSchemaTableName());
        IcebergOutputTableHandle outputTableHandle = new IcebergOutputTableHandle(
                handle.getSchemaName(),
                handle.getIcebergTableName(),
                toPrestoSchema(icebergTable.schema(), typeManager),
                toPrestoPartitionSpec(icebergTable.spec(), typeManager),

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure the table uses Iceberg format version 2 with merge-on-read mode for updates
  2. Rewrite the table at format version 2 (e.g. alter table set TBLPROPERTIES ('format-version'='2')) before running UPDATE
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java:1921 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/8c353533218a1d61. Report an issue: GitHub.