dotnet/machinelearning · error · IndexOutOfRangeException

nameof(row)

Error message

nameof(row)

What it means

An IndexOutOfRangeException thrown at the end of StringDataFrameColumn.AddValueUsingCursor when the cursor's position (row) is greater than the column's current Length. The method accepts a row equal to Length (appending) or less than Length (overwriting in place), but a row beyond Length leaves a gap of uninitialized values, so it refuses by throwing with nameof(row) as the offending argument. It fires when a DataViewRowCursor is advanced further than the number of rows already materialized in the column — typically because rows were skipped or the column was not grown in lockstep with cursor iteration. Unlike the Debug.Assert(getter != null) guard earlier in the method (a debug-only sentinel for a null getter delegate), this is a runtime validation of the row index input, and the value at fault is cursor.Position relative to Length.

Source

Thrown at src/Microsoft.Data.Analysis/DataFrameColumns/StringDataFrameColumn.cs:525

        protected internal override void AddValueUsingCursor(DataViewRowCursor cursor, Delegate getter)
        {
            long row = cursor.Position;
            ReadOnlyMemory<char> value = default;
            Debug.Assert(getter != null, "Excepted getter to be valid");

            (getter as ValueGetter<ReadOnlyMemory<char>>)(ref value);

            if (Length > row)
            {
                this[row] = value.ToString();
            }
            else if (Length == row)
            {
                Append(value.ToString());
            }
            else
            {
                throw new IndexOutOfRangeException(nameof(row));
            }
        }

        protected internal override Delegate GetValueGetterUsingCursor(DataViewRowCursor cursor, DataViewSchema.Column schemaColumn)
        {
            return cursor.GetGetter<ReadOnlyMemory<char>>(schemaColumn);
        }

        public override Dictionary<long, ICollection<long>> GetGroupedOccurrences(DataFrameColumn other, out HashSet<long> otherColumnNullIndices)
        {
            return GetGroupedOccurrences<string>(other, out otherColumnNullIndices);
        }
    }
}

View on GitHub (pinned to 7b76e69cf9)

Solutions

  1. Use Append(value) for adding new rows instead of indexing past Length
  2. Ensure indices are contiguous 0..Length-1 during construction
  3. Check rowIndex <= Length before assigning; only rowIndex == Length appends
  4. Pre-size the column (new StringDataFrameColumn(name, length)) then fill in order

Example fix

// before
column[column.Length + 1] = value; // gap -> throw
// after
column.Append(value);
Defensive patterns

Strategy: validation

Validate before calling

if (rowIndex > column.Length) throw new IndexOutOfRangeException($"row {rowIndex} > length {column.Length}");

Type guard

bool CanAssignAt(long i, long length) => i >= 0 && i <= length; // == length appends

Try / catch

try { column[rowIndex] = value; } catch (IndexOutOfRangeException) { column.Append(value); }

Prevention

When it happens

Trigger: Assigning via the object indexer at a row index greater than the current column length; sparse or skipped-index filling that leaves gaps.

Common situations: Building a column row-by-row with wrong bookkeeping; appending at assumed positions after row deletions; copying from a differently sized source.

Related errors


AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11). Data as JSON: /api/errors/f47fbc95592d7f04. Report an issue: GitHub.