dotnet/machinelearning · error · IndexOutOfRangeException
nameof(row)
Error message
nameof(row)
What it means
AddValueUsingCursor appends to the column only when the cursor's row position equals the column Length; any other position throws IndexOutOfRangeException(nameof(row)). The column is append-only during cursor consumption, so 'row' must track the next append slot exactly.
Source
Thrown at src/Microsoft.Data.Analysis/DataFrameColumns/VBufferDataFrameColumn.cs:208
protected internal override void AddValueUsingCursor(DataViewRowCursor cursor, Delegate getter)
{
long row = cursor.Position;
VBuffer<T> value = default;
Debug.Assert(getter != null, "Excepted getter to be valid");
(getter as ValueGetter<VBuffer<T>>)(ref value);
if (Length > row)
{
this[row] = value;
}
else if (Length == row)
{
Append(value);
}
else
{
throw new IndexOutOfRangeException(nameof(row));
}
}
private VBufferDataFrameColumn<T> CloneImplementation(PrimitiveDataFrameColumn<bool> boolColumn)
{
if (boolColumn.Length > Length)
throw new ArgumentException(Strings.MapIndicesExceedsColumnLength, nameof(boolColumn));
VBufferDataFrameColumn<T> ret = new VBufferDataFrameColumn<T>(Name, 0);
for (long i = 0; i < boolColumn.Length; i++)
{
bool? value = boolColumn[i];
if (value.HasValue && value.Value == true)
ret.Append(this[i]);
}
return ret;
}
private VBufferDataFrameColumn<T> CloneImplementation(PrimitiveDataFrameColumn<long> mapIndices, bool invertMapIndices = false)View on GitHub (pinned to 7b76e69cf9)
Solutions
- Ensure the cursor visits rows sequentially 0..Length-1 and the method is called exactly once per row.
- Append filler/default rows so row == Length when the value arrives.
- Use a fresh column when re-reading data instead of appending to a populated one.
- Guard the call: only invoke when row equals the column's current Length.
Example fix
// before
column.AddValueUsingCursor(cursor, row); // row != column.Length
// after
if (row == column.Length)
column.AddValueUsingCursor(cursor, row);
else
throw new InvalidOperationException($"Expected row {column.Length}, got {row}"); Defensive patterns
Strategy: validation
Validate before calling
if (row != column.Length)
throw new InvalidOperationException($"AddValueUsingCursor requires row == Length ({column.Length}), got {row}"); Type guard
bool canAppendAt(long row, VBufferDataFrameColumn<T> col) => row == col.Length;
Try / catch
try { column.AddValueUsingCursor(cursor, row); }
catch (IndexOutOfRangeException)
{ /* cursor out of sync with column: resync or recreate column */ } Prevention
- Consume cursors strictly sequentially, one call per row.
- Never append to a column that already contains data.
- Use a fresh column per read pass.
- Assert row == Length in debug builds.
When it happens
Trigger: Calling AddValueUsingCursor with row < Length (slot already filled) or row > Length (gap) — e.g. a cursor that skips rows, or calling it twice for the same row.
Common situations: Custom IDataView-to-DataFrame conversion code with a row counter out of sync with the column; appending into a column that already holds data; parallel cursors writing to one column.
Related errors
AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11).
Data as JSON: /api/errors/afb19acdc6fd3069.
Report an issue: GitHub.