apache/iceberg · error · UnsupportedOperationException
Unsupported table change: setting unique key constraints.
Error message
Unsupported table change: setting unique key constraints.
What it means
Iceberg has no native UNIQUE KEY constraint concept — only identifier fields (primary key). When applyUniqueConstraint receives a UniqueConstraint of type UNIQUE_KEY it throws UnsupportedOperationException because UpdateSchema cannot represent it.
Source
Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/util/FlinkAlterTableUtil.java:253
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);
}
}
private static void applyUniqueConstraint(
UpdateSchema pendingUpdate, UniqueConstraint constraint) {
switch (constraint.getType()) {
case PRIMARY_KEY:
pendingUpdate.setIdentifierFields(constraint.getColumns());
break;
case UNIQUE_KEY:
throw new UnsupportedOperationException(
"Unsupported table change: setting unique key constraints.");
default:
throw new UnsupportedOperationException(
"Cannot apply unknown unique constraint: " + constraint.getType().name());
}
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Remove UNIQUE declarations from the DDL; enforce uniqueness upstream or in pipeline logic instead
- Express the closest intent as identifier fields (setIdentifierFields) if the columns can act as a primary key
- Catch UnsupportedOperationException and document to users that Iceberg/Flink path supports only PRIMARY_KEY constraints
Example fix
// before
ALTER TABLE t ADD UNIQUE (email);
// after
-- enforce uniqueness in pipeline, or:
table.updateSchema().setIdentifierFields("email").commit(); Defensive patterns
Strategy: validation
Validate before calling
boolean hasUniqueKey = changes.stream()
.filter(c -> c instanceof TableChange.AddUniqueConstraint || c instanceof TableChange.ModifyUniqueConstraint)
.map(c -> c instanceof TableChange.AddUniqueConstraint
? ((TableChange.AddUniqueConstraint) c).getConstraint()
: ((TableChange.ModifyUniqueConstraint) c).getNewConstraint())
.anyMatch(u -> u.getType() == ConstraintType.UNIQUE_KEY);
if (hasUniqueKey) throw new IllegalArgumentException("Iceberg supports only PRIMARY_KEY constraints"); Type guard
static boolean isPrimaryKeyConstraint(UniqueConstraint u) { return u.getType() == ConstraintType.PRIMARY_KEY; } Try / catch
try { FlinkAlterTableUtil.applySchemaChanges(update, changes); }
catch (UnsupportedOperationException e) {
if (e.getMessage().contains("unique key constraints")) { /* strip UNIQUE DDL and warn user */ }
throw e;
} Prevention
- Do not declare UNIQUE keys in Iceberg DDL via Flink
- Enforce uniqueness in pipeline/application logic
- Use identifier fields only where a true primary key exists
When it happens
Trigger: ALTER TABLE ... ADD UNIQUE(...) or a Flink connector config declaring unique keys on an Iceberg table routed to applySchemaChanges → applyUniqueConstraint.
Common situations: Porting warehouse DDL that uses UNIQUE constraints (e.g. from MySQL) to Iceberg; Flink SQL CREATE TABLE with UNIQUE declared; data quality tooling asserting uniqueness via constraint DDL.
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
- Unsupported table change: setting unique key constraints.
- Failed to list partitions of table %s
- Unsupported YearMonthIntervalType.
- Unsupported DayTimeIntervalType.
- Unsupported DistinctType.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/342f3afd8cbe37b8.
Report an issue: GitHub.