apache/iceberg · error · UnsupportedOperationException
Cannot apply unknown unique constraint: {constraint.getType(
Error message
Cannot apply unknown unique constraint: {constraint.getType().name()} What it means
When applying Flink schema changes to an Iceberg table, the unique-constraint applicator only handles PRIMARY_KEY constraints; UNIQUE_KEY or any other constraint type is rejected. The default branch catches constraint types not explicitly handled, meaning the Flink-to-Iceberg mapping does not support this constraint kind. This is a deliberate guard: Iceberg tables do not model UNIQUE constraints like relational engines do.
Source
Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/util/FlinkAlterTableUtil.java:256
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 the UNIQUE constraint from the Flink DDL; Iceberg does not enforce unique keys
- Keep only PRIMARY KEY constraints, which are mapped to Iceberg identifier fields
- Enforce uniqueness at the engine/job level (e.g. upsert logic) instead of the catalog
- If PRIMARY_KEY support is what you need, verify constraint.getType() is PRIMARY_KEY before calling
Example fix
// before
CREATE TABLE t (id INT, name STRING, UNIQUE (name)) WITH ('connector'='iceberg');
// after
CREATE TABLE t (id INT, name STRING, PRIMARY KEY (id) NOT ENFORCED) WITH ('connector'='iceberg'); Defensive patterns
Strategy: validation
Validate before calling
if (constraint.getType() != UniqueConstraint.Type.PRIMARY_KEY) {
throw new IllegalArgumentException(
"Iceberg supports only PRIMARY_KEY constraints, got: " + constraint.getType());
}
applySchemaChange(update); Prevention
- Only use PRIMARY KEY (NOT ENFORCED) in Flink DDL targeting Iceberg tables
- Avoid copying UNIQUE constraints when migrating schemas from JDBC/Hive to Iceberg
- Keep a schema-mapping layer that drops unsupported constraint types explicitly
When it happens
Trigger: Calling applySchemaChanges/applyUniqueConstraint with a Flink table change whose UniqueConstraint.getType() is UNIQUE_KEY or any non-PRIMARY_KEY type, e.g. a CREATE TABLE or ALTER TABLE with a UNIQUE constraint in Flink SQL against an Iceberg catalog.
Common situations: Migrating Flink SQL DDL written for JDBC/Hive tables (which support UNIQUE keys) to an Iceberg catalog; schema-sync tools that copy full constraint sets; ORMs generating UNIQUE KEY definitions.
Related errors
- Default values are not supported
- UnsupportedOperationException
- Unknown field ordinal:
- Unknown move type:
- Altering schema is not supported in the old alterTable API.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/a7712f928e67de78.
Report an issue: GitHub.