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.

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.

Appendix: 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)