apache/iceberg · error · UnsupportedOperationException
Unknown move type:
Error message
Unknown move type:
What it means
When applying schema moves (Move.first, Move.before, Move.after) during SchemaUpdate.commit, an exhaustive switch over move.type() handles the known kinds. Any Move implementation outside the three supported kinds reaches the default branch and throws UnsupportedOperationException. This guards against future or custom move types the reordering logic does not implement.
Source
Thrown at core/src/main/java/org/apache/iceberg/SchemaUpdate.java:813
break;
case BEFORE:
Types.NestedField before =
Iterables.find(reordered, field -> field.fieldId() == move.referenceFieldId());
int beforeIndex = reordered.indexOf(before);
// insert the new node at the index of the existing node
reordered.add(beforeIndex, toMove);
break;
case AFTER:
Types.NestedField after =
Iterables.find(reordered, field -> field.fieldId() == move.referenceFieldId());
int afterIndex = reordered.indexOf(after);
reordered.add(afterIndex + 1, toMove);
break;
default:
throw new UnsupportedOperationException("Unknown move type: " + move.type());
}
}
return reordered;
}
/** Represents a requested column move in a struct. */
private static class Move {
private enum MoveType {
FIRST,
BEFORE,
AFTER
}
@Override
public String toString() {
String suffix = "";
if (type != MoveType.FIRST) {View on GitHub (pinned to 86d9c8fc54)
Solutions
- Ensure the client library version producing the Move matches the version applying the update
- Only construct moves via updateSchema().moveFirst/moveBefore/moveAfter
- Upgrade iceberg-core so all Move types are supported
Defensive patterns
Strategy: try-catch
Validate before calling
if (move.type() != Move.MoveType.FIRST && move.type() != Move.MoveType.BEFORE && move.type() != Move.MoveType.AFTER) { throw new IllegalArgumentException("Unsupported move type"); } Try / catch
try { update.apply(); } catch (UnsupportedOperationException e) { if (e.getMessage().startsWith("Unknown move type")) { /* version mismatch: upgrade client */ } else { throw e; } } Prevention
- Keep iceberg-core versions consistent across producer and consumer of schema updates
- Only create moves via the public UpdateSchema.move* APIs
- Avoid subclassing Move with custom types
When it happens
Trigger: Applying a Move whose type() is not FIRST, BEFORE, or AFTER — normally only possible with a custom Move implementation or a version mismatch where a newer move kind is passed to an older SchemaUpdate.
Common situations: Mixed client/server versions during rolling upgrades; custom TableOperations or wrapped Move objects from another Iceberg-compatible implementation.
Related errors
- Cannot drop identifier fields in non-Iceberg table: $table
- Cannot set identifier fields in non-Iceberg table: $table
- %s does not implement deleteFile
- %s does not implement addFile
- %s does not implement dataSequenceNumber
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ea497af40b07ac94.
Report an issue: GitHub.