apache/iceberg · error · IllegalArgumentException
Unknown position for reorder:
Error message
Unknown position for reorder:
What it means
Thrown when applying a Spark TableChange.UpdateColumnPosition whose position is neither TableChange.After nor TableChange.First. Spark3Util only knows how to map these two position kinds onto Iceberg's moveBefore/moveAfter/moveFirst operations.
Source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:232
}
}
return pendingUpdate;
}
private static void apply(UpdateSchema pendingUpdate, TableChange.UpdateColumnPosition update) {
Preconditions.checkArgument(update.position() != null, "Invalid position: null");
if (update.position() instanceof TableChange.After) {
TableChange.After after = (TableChange.After) update.position();
String referenceField = peerName(update.fieldNames(), after.column());
pendingUpdate.moveAfter(DOT.join(update.fieldNames()), referenceField);
} else if (update.position() instanceof TableChange.First) {
pendingUpdate.moveFirst(DOT.join(update.fieldNames()));
} else {
throw new IllegalArgumentException("Unknown position for reorder: " + update.position());
}
}
private static void apply(UpdateSchema pendingUpdate, TableChange.AddColumn add) {
Preconditions.checkArgument(
add.isNullable(),
"Incompatible change: cannot add required column: %s",
leafName(add.fieldNames()));
if (add.defaultValue() != null) {
throw new UnsupportedOperationException(
String.format(
"Cannot add column %s since setting default values in Spark is currently unsupported",
leafName(add.fieldNames())));
}
Type type = SparkSchemaUtil.convert(add.dataType());
pendingUpdate.addColumn(
parentName(add.fieldNames()), leafName(add.fieldNames()), type, add.comment());View on GitHub (pinned to 86d9c8fc54)
Solutions
- Use TableChange.After or TableChange.First for reorders
- Upgrade Iceberg if a new Spark position type was introduced
- Convert the position manually via updatePosition/moveAfter APIs
Example fix
// before TableChange.updateColumnPosition(new MyCustomPosition(), col); // after TableChange.updateColumnPosition(TableChange.after(previousCol), col);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(pos instanceof TableChange.After || pos instanceof TableChange.First)) { throw new IllegalArgumentException("Position must be After or First: " + pos); } Type guard
boolean knownPosition(TableChange.ColumnPosition p) { return p instanceof TableChange.After || p instanceof TableChange.First; } Try / catch
try { spark.sql("ALTER TABLE t COLUMN REORDER ..."); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unknown position for reorder")) { /* rebuild using After/First */ } else throw e; } Prevention
- Build reorders only with TableChange.After/First
- Avoid custom ColumnPosition subclasses
- Map engine-specific positions to Iceberg's before applying
When it happens
Trigger: Applying an UpdateColumnChange with a custom or future position subclass, or a position type produced by an engine/extension other than After/First.
Common situations: Engine extensions (e.g. other catalogs) generating custom position kinds; Spark upgrades adding new position types; manually constructed UpdateColumnPosition objects.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unknown position for reorder: ${update.position()}
- Unknown position for reorder: ${update.position()}
- Spark does not support time fields
- Unsupported type:
- Encountered an unsupported ORC type during a write from Spar
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/d8a09e141517bf6f.
Report an issue: GitHub.