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

  1. Ensure the cursor visits rows sequentially 0..Length-1 and the method is called exactly once per row.
  2. Append filler/default rows so row == Length when the value arrives.
  3. Use a fresh column when re-reading data instead of appending to a populated one.
  4. 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

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.