apache/iceberg · error · IllegalArgumentException
No column at position
Error message
No column at position ${colPos} What it means
PositionDelete models a row as a 3-element struct: position 0 = file path, 1 = position, 2 = the deleted row (nullable). get(colPos) throws IllegalArgumentException for any index outside 0..2, since there are only three logical columns.
Solutions
- Only use colPos values 0, 1, or 2; access row fields through the row object (a StructLike or row type) instead
- Bounds-check colPos against the logical arity of 3 before calling get
- If iterating generically, cap iteration at PositionDelete's size (3)
- For row-level columns, cast get(2) to the row type and index into that
Example fix
// before
for (int i = 0; i < schema.columns().size(); i++) {
Object v = positionDelete.get(i); // throws at i >= 3
}
// after
Object path = positionDelete.get(0);
Long pos = positionDelete.get(1);
R row = positionDelete.get(2); // access row fields via row
Defensive patterns
Strategy: validation
Validate before calling
if (colPos < 0 || colPos > 2) {
throw new IllegalArgumentException("PositionDelete has only 3 columns (0=path, 1=pos, 2=row)");
} Type guard
static boolean isValidColumn(int colPos) {
return colPos >= 0 && colPos <= 2;
} Try / catch
try {
return positionDelete.get(colPos);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("colPos must be 0-2 for PositionDelete", e);
} Prevention
- Remember PositionDelete arity is fixed at 3 (path, position, row)
- Index row fields on the row object from get(2), not via PositionDelete.get
- Guard generic schema-driven loops with arity min(schema.size(), 3)
- Add asserts in helper utilities that wrap PositionDelete access
When it happens
Trigger: Calling PositionDelete.get(3) or higher (or negative), e.g. when generic struct-like access code iterates a schema with more columns than PositionDelete actually has.
Common situations: Generic readers projecting a table schema's column count onto a PositionDelete instance; off-by-one loops over columns; assuming the row struct's fields are addressable directly via get().
Related errors
- Cannot add duplicate partition field name
- Cannot create expression literal from
- Cannot create metadata table for table
- Cannot create the table with 'connector'='iceberg' table…
- Cannot find field in
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/36a37cd48c403002.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/deletes/PositionDelete.java:70
return path;
}
public long pos() {
return pos;
}
@Override
@SuppressWarnings("unchecked")
public <T> T get(int colPos, Class<T> javaClass) {
switch (colPos) {
case 0:
return (T) path;
case 1:
return (T) (Long) pos;
case 2:
return (T) row;
default:
throw new IllegalArgumentException("No column at position " + colPos);
}
}
@Override
public <T> void set(int colPos, T value) {
switch (colPos) {
case 0:
this.path = (CharSequence) value;
break;
case 1:
this.pos = (Long) value;
break;
case 2:
this.row = (R) value;
break;
default:
throw new IllegalArgumentException("No column at position " + colPos);
}View on GitHub (pinned to 86d9c8fc54)