apache/iceberg · error · IllegalArgumentException
Cannot get value for invalid index
Error message
Cannot get value for invalid index: <index>
What it means
Thrown by a positional accessor (e.g. the delete-vector record reader's get) when asked for a value at an index that the underlying structure does not have. These composite readers only expose a fixed number of positional fields (here 0 and 1 for path and pos of a delete); any other index is invalid and raises IllegalArgumentException.
Solutions
- Only access indices 0..numFields-1 of the composite reader; verify the index against the struct width
- Update the switch mapping if new fields (e.g. sequence numbers) were added to the delete schema
- Check the writerToFieldIndex mapping when Unknown columns are skipped so indices align
Example fix
// before: blindly accessing a third column
Object seq = reader.get(2);
// after: guard the index
if (index >= 0 && index < numFields) { value = reader.get(index); } Defensive patterns
Strategy: type-guard
Validate before calling
if (index < 0 || index >= reader.numFields()) {
throw new IndexOutOfBoundsException("reader index " + index + " out of range");
} Type guard
boolean isValidIndex(int index, int numFields) { return index >= 0 && index < numFields; } Try / catch
try {
value = accessor.get(index);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Cannot get value for invalid index")) {
// re-map index via writerToFieldIndex before retrying
} else throw e;
} Prevention
- Compute indices from the struct type, never hardcode
- Use writerToFieldIndex when Unknown columns are skipped
- Update composite readers when delete schema columns change
When it happens
Trigger: Calling get(int index) on the reader's internal position-accessor with an index other than 0 or 1, usually from code that assumes a different field layout or passes a writer/field index computed against a different struct type.
Common situations: Positional deletes/vectorized delete readers where the writer-index mapping is off by the number of columns; code changes adding columns without updating the switch; generic code iterating indices beyond the record width.
Related errors
- AlwaysFalse is a placeholder only
- AlwaysTrue is a placeholder only
- Avro writer does not support variant types
- Batch reading is not supported in non-vectorized reader
- Buffer size of is larger than requested size of
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/acc9a2eeb0f122ff.
Report an issue: GitHub.
Appendix: source
Thrown at parquet/src/main/java/org/apache/iceberg/parquet/ParquetValueWriters.java:733
public static class PositionDeleteStructWriter<R> extends StructWriter<PositionDelete<R>> {
private final Function<CharSequence, ?> pathTransformFunc;
public PositionDeleteStructWriter(
StructWriter<?> replacedWriter, Function<CharSequence, ?> pathTransformFunc) {
super(Arrays.asList(replacedWriter.writers));
this.pathTransformFunc = pathTransformFunc;
}
@Override
protected Object get(PositionDelete<R> delete, int index) {
switch (index) {
case 0:
return pathTransformFunc.apply(delete.path());
case 1:
return delete.pos();
}
throw new IllegalArgumentException("Cannot get value for invalid index: " + index);
}
}
/** Returns a mapping from writer index to field index, skipping Unknown columns. */
static int[] writerToFieldIndex(Types.StructType struct, int numWriters) {
if (null == struct) {
return IntStream.rangeClosed(0, numWriters).toArray();
}
List<Types.NestedField> recordFields = struct.fields();
// value writer index to record field index
int[] indexes = new int[numWriters];
int writerIndex = 0;
for (int pos = 0; pos < recordFields.size(); pos += 1) {
if (recordFields.get(pos).type().typeId() != org.apache.iceberg.types.Type.TypeID.UNKNOWN) {
indexes[writerIndex] = pos;
writerIndex += 1;View on GitHub (pinned to 86d9c8fc54)