dotnet/machinelearning · error · InvalidOperationException

Invalid call to 'GetGetter'

Error message

Invalid call to 'GetGetter'

What it means

DataViewSchema.GetGetter<TValue> returns the typed ValueGetter<TValue> for a column, but the stored getter for that column index is either not a ValueGetter<TValue> of the requested type or is null. This means the caller asked for the column's value with a TValue that does not match the column's declared type. The library throws because returning null would silently break downstream row cursors.

Source

Thrown at src/Microsoft.ML.DataView/DataViewSchema.cs:229

            private void CheckGetter<TValue>(Delegate getter)
            {
                var typedGetter = getter as ValueGetter<TValue>;
                if (typedGetter == null)
                    throw new ArgumentNullException(nameof(getter), $"Getter of type '{typeof(TValue)}' expected, but {getter.GetType()} found");
            }

            /// <summary>
            /// Get a getter delegate for one value of the annotations row.
            /// </summary>
            public ValueGetter<TValue> GetGetter<TValue>(DataViewSchema.Column column)
            {
                if (column.Index >= _getters.Length)
                    throw new ArgumentException(nameof(column));
                var typedGetter = _getters[column.Index] as ValueGetter<TValue>;
                if (typedGetter == null)
                {
                    Debug.Assert(_getters[column.Index] != null);
                    throw new InvalidOperationException($"Invalid call to '{nameof(GetGetter)}'");
                }
                return typedGetter;
            }

            /// <summary>
            /// Get the value of an annotation, by annotation kind (aka column name).
            /// </summary>
            public void GetValue<TValue>(string kind, ref TValue value)
            {
                var column = Schema.GetColumnOrNull(kind);
                if (column == null)
                    throw new InvalidOperationException($"Invalid call to '{nameof(GetValue)}'");
                GetGetter<TValue>(column.Value)(ref value);
            }

            public override string ToString() => string.Join(", ", Schema.Select(x => x.Name));

            internal Delegate GetGetterInternal(int index)

View on GitHub (pinned to 7b76e69cf9)

Solutions

  1. Check column.Type.RawType (or GetAnnotationType) and use exactly that type as TValue in GetGetter<TValue>
  2. Use the weakly-typed GetGetterInternal/Delegate path and convert with Utils.MarshalActionInvoke (or MarshalInvoke) instead of a fixed generic
  3. Inspect the column's DataViewType and slot structure before writing the cursor loop; if the type is dynamic, dispatch per-type

Example fix

// before
var getter = schema.GetGetter<int>(schema["Features"]);
// after
if (schema["Features"].Type.RawType == typeof(VBuffer<float>))
    var getter = schema.GetGetter<VBuffer<float>>(schema["Features"]);
Defensive patterns

Strategy: type-guard

Validate before calling

var col = schema["Features"];
if (col.Type.RawType != typeof(VBuffer<float>))
    throw new InvalidOperationException($"Expected VBuffer<float>, got {col.Type.RawType}");
var getter = schema.GetGetter<VBuffer<float>>(col);

Type guard

bool IsTyped<TValue>(DataViewSchema.Column c) => c.Type.RawType == typeof(TValue);

Try / catch

try { getter = schema.GetGetter<TValue>(col); }
catch (InvalidOperationException)
{
    var actual = col.Type.RawType;
    getter = MarshalGetter<TValue>(col, actual); // dispatch on actual type
}

Prevention

When it happens

Trigger: Calling schema.GetGetter<int>(col) on a column whose actual value type is float/ReadOnlyMemory<char>/VBuffer<etc>; casting a weakly-typed Delegate getter to the wrong ValueGetter<TValue>; reusing a getter obtained from a different schema after a transform changed column types.

Common situations: Hand-rolling a row cursor over a DataView and hard-coding a TValue; using GetGetter inside annotation/annotation-kind lookups with a mismatched generic; code written against one pipeline version breaking after upstream transforms change a column's type.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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