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

  1. Use TableChange.After or TableChange.First for reorders
  2. Upgrade Iceberg if a new Spark position type was introduced
  3. 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

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


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