{"record":{"id":"c0d503c7ae3c5c65","repo":"dotnet/machinelearning","slug":"type-rawtype-must-be-of-type-typeof-tvalue-full","errorCode":null,"errorMessage":"type.RawType must be of type '{typeof(TValue).FullName}'.","messagePattern":"type\\.RawType must be of type '(.+?)'\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.DataView/DataViewSchema.cs","lineNumber":304,"sourceCode":"                /// <summary>\n                /// Add one annotation column, strongly-typed version.\n                /// </summary>\n                /// <typeparam name=\"TValue\">The type of the value.</typeparam>\n                /// <param name=\"name\">The annotation name.</param>\n                /// <param name=\"type\">The annotation type.</param>\n                /// <param name=\"getter\">The getter delegate.</param>\n                /// <param name=\"annotations\">Annotations of the input column. Note that annotations on an annotation column is somewhat rare\n                /// except for certain types (for example, slot names for a vector, key values for something of key type).</param>\n                public void Add<TValue>(string name, DataViewType type, ValueGetter<TValue> getter, Annotations annotations = null)\n                {\n                    if (string.IsNullOrEmpty(name))\n                        throw new ArgumentNullException(nameof(name));\n                    if (type == null)\n                        throw new ArgumentNullException(nameof(type));\n                    if (getter == null)\n                        throw new ArgumentNullException(nameof(getter));\n                    if (type.RawType != typeof(TValue))\n                        throw new ArgumentException($\"{nameof(type)}.{nameof(type.RawType)} must be of type '{typeof(TValue).FullName}'.\", nameof(type));\n\n                    _items.Add((name, type, getter, annotations));\n                }\n\n                /// <summary>\n                /// Add one annotation column, weakly-typed version.\n                /// </summary>\n                /// <param name=\"name\">The annotation name.</param>\n                /// <param name=\"type\">The annotation type.</param>\n                /// <param name=\"getter\">The getter delegate that provides the value. Note that the type of the getter is still checked\n                /// inside this method.</param>\n                /// <param name=\"annotations\">Annotations of the input column. Note that annotations on an annotation column is somewhat rare\n                /// except for certain types (for example, slot names for a vector, key values for something of key type).</param>\n                public void Add(string name, DataViewType type, Delegate getter, Annotations annotations = null)\n                {\n                    if (string.IsNullOrEmpty(name))\n                        throw new ArgumentNullException(nameof(name));\n                    if (type == null)","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.DataView/DataViewSchema.cs#L286-L322","documentation":"Builder.Add<TValue> enforces that the DataViewType's RawType equals typeof(TValue): the static generic parameter and the declared logical type must agree, otherwise the ValueGetter<TValue> would read the wrong CLR representation. Mismatch throws ArgumentException naming 'type'.","triggerScenarios":"Adding a column typed as VBuffer<float> while TValue is float[]; using NumberDataViewType.Double (RawType double) with a ValueGetter<float>; key types whose RawType is uint paired with an int getter.","commonSituations":"Generic helper code that fixes TValue at compile time but receives arbitrary DataViewTypes at runtime; copy-pasted annotation code (e.g. slot names use VBuffer<ReadOnlyMemory<char>>) adapted to scalar columns without changing TValue.","solutions":["Set TValue to exactly column.Type.RawType (or the well-known annotation type, e.g. VBuffer<ReadOnlyMemory<char>> for SlotNames)","Derive the getter's generic type from the type first, then call the weakly-typed Add(name, type, Delegate) overload which marshals via MarshalActionInvoke","Use AnnotationUtils/TypeUtils helpers that pick the correct TValue per DataViewType"],"exampleFix":"// before\nbuilder.Add<VBuffer<float>>(\"SlotNames\", NumberDataViewType.Single, getter);\n// after\nbuilder.Add<float>(\"SlotNames\", NumberDataViewType.Single, getter); // TValue matches RawType\n// or for vectors:\nbuilder.Add<VBuffer<float>>(\"Features\", new VectorDataViewType(NumberDataViewType.Single), getter);","handlingStrategy":"type-guard","validationCode":"if (type.RawType != typeof(TValue))\n    throw new InvalidOperationException($\"Use TValue={type.RawType.Name} for type {type}\");\nbuilder.Add(name, type, getter);","typeGuard":"bool TypeMatches<TValue>(DataViewType t) => t.RawType == typeof(TValue);","tryCatchPattern":"try { builder.Add<TValue>(name, type, getter); }\ncatch (ArgumentException e) when (e.ParamName == \"type\")\n{\n    // fall back to weakly-typed dispatch\n    builder.Add(name, type, (Delegate)getter);\n}","preventionTips":["Match TValue to type.RawType exactly; consult TypeUtils for annotation conventions (SlotNames => VBuffer<ReadOnlyMemory<char>>)","For generic code, dispatch on RawType via MarshalActionInvoke instead of fixing TValue","Verify key-type columns use their underlying raw type (e.g. uint) as TValue"],"tags":["dotnet","mlnet","generics","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}