apache/iceberg · error · IllegalArgumentException

Unknown position for reorder: ${update.position()}

Error message

Unknown position for reorder: ${update.position()}

What it means

When applying a TableChange.UpdateColumnPosition, Iceberg recognizes only After and First positions for reordering columns. Any other position type (e.g. Spark's default first/last encodings) triggers this IllegalArgumentException because there is no Iceberg move operation for it.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:228

      }
    }

    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. Only issue AFTER <col> or FIRST column reorders through this path
  2. Normalize the position to TableChange.After or TableChange.First before calling applySchemaChanges
  3. Upgrade Iceberg if a new Spark position type isn't yet mapped

Example fix

// before
new TableChange.UpdateColumnPosition(path, customPosition)
// after
new TableChange.UpdateColumnPosition(path, TableChange.First.getInstance())
Defensive patterns

Strategy: type-guard

Validate before calling

if (update.position() != null && !(update.position() instanceof TableChange.After) && !(update.position() instanceof TableChange.First)) { throw new IllegalArgumentException("Unsupported position: " + update.position()); }

Type guard

boolean isSupportedPosition(TableChange.ColumnPosition p) { return p instanceof TableChange.After || p instanceof TableChange.First; }

Try / catch

try { Spark3Util.applySchemaChanges(table, changes); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unknown position for reorder")) { /* normalize to After/First */ } else throw e; }

Prevention

When it happens

Trigger: ALTER TABLE ... ALTER COLUMN x AFTER/first-style changes where the UpdateColumnPosition carries a position instance other than TableChange.After or TableChange.First.

Common situations: Custom ALTER TABLE reordering logic or an engine integration emitting an unsupported position type; internal mismatches when a Spark release changes its position classes.

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/15565ac856169549. Report an issue: GitHub.