apache/iceberg · error · UnsupportedOperationException

Cannot apply unknown modify-column change:

Error message

Cannot apply unknown modify-column change: 

What it means

applyModifyColumn recognizes only specific Modify* change types (type, comment, position, rename); anything else hits this final throw. It means an unhandled TableChange modify-column variant reached the schema update logic.

Source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/util/FlinkAlterTableUtil.java:227

      applyModifyColumnPosition(pendingUpdate, modifyPosition);
    } else if (modifyColumn instanceof TableChange.ModifyPhysicalColumnType) {
      TableChange.ModifyPhysicalColumnType modifyType =
          (TableChange.ModifyPhysicalColumnType) modifyColumn;
      Type type = FlinkSchemaUtil.convert(modifyType.getNewType().getLogicalType());
      String columnName = modifyType.getOldColumn().getName();
      pendingUpdate.updateColumn(columnName, type.asPrimitiveType());
      if (modifyType.getNewColumn().getDataType().getLogicalType().isNullable()) {
        pendingUpdate.makeColumnOptional(columnName);
      } else {
        pendingUpdate.requireColumn(columnName);
      }
    } else if (modifyColumn instanceof TableChange.ModifyColumnComment) {
      TableChange.ModifyColumnComment modifyComment =
          (TableChange.ModifyColumnComment) modifyColumn;
      pendingUpdate.updateColumnDoc(
          modifyComment.getOldColumn().getName(), modifyComment.getNewComment());
    } else {
      throw new UnsupportedOperationException(
          "Cannot apply unknown modify-column change: " + modifyColumn);
    }
  }

  private static void applyModifyColumnPosition(
      UpdateSchema pendingUpdate, TableChange.ModifyColumnPosition modifyColumnPosition) {
    TableChange.ColumnPosition newPosition = modifyColumnPosition.getNewPosition();
    if (newPosition instanceof TableChange.First) {
      pendingUpdate.moveFirst(modifyColumnPosition.getOldColumn().getName());
    } else if (newPosition instanceof TableChange.After) {
      TableChange.After after = (TableChange.After) newPosition;
      pendingUpdate.moveAfter(modifyColumnPosition.getOldColumn().getName(), after.column());
    } else {
      throw new UnsupportedOperationException(
          "Cannot apply unknown modify-column-position change: " + modifyColumnPosition);
    }
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Upgrade the Iceberg Flink runtime to match your Flink version
  2. Inspect change.getClass().getName() in the message and check whether that subtype is supported in your Iceberg version
  3. Convert the change manually via UpdateSchema APIs (updateColumnType, updateColumnDoc, etc.) instead of relying on the utility

Example fix

// before
// unknown modify change thrown
// after
if (change instanceof TableChange.ModifyColumnType) {
  pendingUpdate.updateColumn type(...); // use supported UpdateSchema operations directly
}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean supported = change instanceof TableChange.ModifyColumnType || change instanceof TableChange.ModifyColumnComment || change instanceof TableChange.ModifyColumnPosition || change instanceof TableChange.RenameColumn;
if (!supported) throw new IllegalArgumentException("Unsupported modify change: " + change.getClass());

Type guard

static boolean isSupportedModifyChange(TableChange c) {
  return c instanceof TableChange.ModifyColumnType || c instanceof TableChange.ModifyColumnComment
      || c instanceof TableChange.ModifyColumnPosition || c instanceof TableChange.RenameColumn;
}

Try / catch

try { FlinkAlterTableUtil.applySchemaChanges(update, changes); }
catch (UnsupportedOperationException e) {
  if (e.getMessage().startsWith("Cannot apply unknown modify-column change")) { log.error("Unhandled modify variant: {}", changes); }
  throw e;
}

Prevention

When it happens

Trigger: Passing a ModifyColumnPosition variant or new Modify* subtype not covered by the if/else chain into applySchemaChanges; custom Flink change types.

Common situations: Version mismatch between Flink planner and iceberg-flink module; hand-built TableChange lists; newly added Flink change kinds used with an older Iceberg runtime.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/fb07a232785eca57. Report an issue: GitHub.