{"record":{"id":"3007507b14454fda","repo":"MonoGame/MonoGame","slug":"unhandled-primitive-type-type-fullname","errorCode":null,"errorMessage":"Unhandled primitive type `{type.FullName}`!","messagePattern":"Unhandled primitive type `(.+?)`!","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/IntermediateSerializer.cs","lineNumber":175,"sourceCode":"            {\n                serializerType = serializerType.MakeGenericType(type.GetGenericArguments());\n                serializer = (ContentTypeSerializer)Activator.CreateInstance(serializerType)!;\n            }\n            else if (type.IsEnum)\n            {\n                serializer = new EnumSerializer(type);\n            }\n            else if (typeof(IList).IsAssignableFrom(type) && !GenericCollectionHelper.IsGenericCollectionType(type, true))\n            {\n                // Special handling for non-generic IList types. By the time we get here,\n                // generic collection types will already have been handled by one of the known serializers.\n                serializer = new NonGenericIListSerializer(type);\n            }\n            else\n            {\n                // The reflective serializer is not for primitive types!\n                if (type.IsPrimitive)\n                    throw new NotImplementedException($\"Unhandled primitive type `{type.FullName}`!\");\n\n                // We still don't have a serializer then we\n                // fallback to the reflection based serializer.\n                serializer = new ReflectiveSerializer(type);\n            }\n\n            Debug.Assert(serializer.TargetType == type, \"Target type mismatch!\");\n\n            // We cache the serializer before we initialize it to\n            // avoid a stack overflow on recursive types.\n            _serializers.Add(type, serializer);\n            serializer.Initialize(this);\n\n            return serializer;\n        }\n\n        internal GenericCollectionHelper GetCollectionHelper(Type type)\n        {","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/MonoGame/MonoGame/blob/1d71bbd0ff4071a03caa583aa3bc56b85924a819/MonoGame.Framework.Content.Pipeline/Serialization/Intermediate/IntermediateSerializer.cs#L157-L193","documentation":"GetTypeSerializer falls back to the ReflectiveSerializer for unknown types, but reflection-based serialization is intentionally forbidden for CLR primitives. If a primitive numeric/pointer type has no registered ContentTypeSerializer, the lookup throws NotImplementedException rather than mis-serializing it by reflection.","triggerScenarios":"A type graph containing a primitive type for which no explicit serializer is registered. In practice this is `IntPtr`/`UIntPtr`/`nint`/`nuint` (which report IsPrimitive == true in modern .NET) used as a serializable field/property, since int/float/double/etc. all have dedicated serializers.","commonSituations":"Adding a native-handle-sized field (`IntPtr handle`) to a pipeline-serializable class, or targeting a runtime where a previously-registered primitive serializer was removed.","solutions":["Do not serialize native pointer/handle primitives; wrap them in a non-primitive type or exclude them with [ContentSerializerIgnore].","Store the value as a serializable `long`/`ulong` and convert to IntPtr at use sites.","Register a custom ContentTypeSerializer for the primitive type if serialization is genuinely required."],"exampleFix":"// before\npublic class GpuResource\n{\n    public IntPtr Handle { get; set; }\n}\n\n// after\npublic class GpuResource\n{\n    public long HandleValue { get; set; }\n    [ContentSerializerIgnore]\n    public IntPtr Handle { get => (IntPtr)HandleValue; set => HandleValue = (long)value; }\n}","handlingStrategy":"type-guard","validationCode":"// Reject serializable members whose primitive type has no registered serializer\nvar ptrTypes = typeof(T).GetFields()\n    .Where(f => f.FieldType.IsPrimitive && !typeof(bool).IsAssignableFrom(f.FieldType)\n        && !new[] { typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int),\n            typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(char) }\n            .Contains(f.FieldType));\nif (ptrTypes.Any())\n    throw new NotSupportedException(\"Unserializable primitive member: \" + string.Join(\", \", ptrTypes.Select(f => f.Name)));","typeGuard":"static bool IsSerializablePrimitive(Type t) =>\n    !t.IsPrimitive || new[] { typeof(bool), typeof(byte), typeof(sbyte), typeof(short),\n        typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong),\n        typeof(float), typeof(double), typeof(char) }.Contains(t);","tryCatchPattern":"try { IntermediateSerializer.Serialize(writer, value, path); }\ncatch (NotImplementedException ex) when (ex.Message.Contains(\"Unhandled primitive\"))\n{\n    // replace the IntPtr/nint member with a long, or mark it [ContentSerializerIgnore]\n}","preventionTips":["Never expose IntPtr/UIntPtr/nint as serializable members; store as long/ulong.","Run a reflection scan over pipeline data types for unhandled primitives.","Unit-test round-trip for every serializable type."],"tags":["csharp","monogame","content-pipeline","serialization","primitives"],"backgroundTag":null,"analyzedSha":"1d71bbd0ff4071a03caa583aa3bc56b85924a819","analyzedAt":"2026-08-13T17:10:33.625Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}