apache/iceberg · error · java.lang.IllegalArgumentException

Unknown position for reorder: <update.position()>

Error message

Unknown position for reorder: <update.position()>

What it means

When applying a TableChange.UpdateColumnPosition, Spark3Util translates the requested position into a move on the pending UpdateSchema. Only After and First positions are recognized; any other position type (e.g. Default) cannot be expressed and throws IllegalArgumentException.

Source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:225

      }
    }

    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 only TableChange.After or TableChange.First positions when issuing reorder changes
  2. Translate a Default position into an explicit First/After or drop the reordering request
  3. Inspect the change source to confirm the position subtype before calling the utility

Example fix

// before
new TableChange.UpdateColumnPosition(new TableChange.Default(), fieldNames);
// after
new TableChange.UpdateColumnPosition(TableChange.After.of(namesBefore), fieldNames);
Defensive patterns

Strategy: validation

Validate before calling

if (!(pos instanceof TableChange.After) && !(pos instanceof TableChange.First)) {
  throw new IllegalArgumentException("Only After/First positions are supported, got: " + pos);
}

Try / catch

try {
  applySchemaChanges(table, changes);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Unknown position for reorder")) {
    // re-issue with an explicit After/First position
  }
}

Prevention

When it happens

Trigger: ALTER TABLE ... ALTER COLUMN ... position DDL translated to a position type other than TableChange.After or TableChange.First reaching Spark3Util.apply(UpdateSchema, UpdateColumnPosition).

Common situations: Programmatic DDL translation where a custom or default position was emitted; new position types added in Spark that Iceberg's converter does not handle.

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/828c2fe857fa3143. Report an issue: GitHub.