{"record":{"id":"5dda5d31ac2a126d","repo":"stride3d/stride","slug":"type-0-is-not-a-primitive-primitivedescriptor","errorCode":null,"errorMessage":"Type [{0}] is not a primitive","messagePattern":"Type \\[(.+?)\\] is not a primitive","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Reflection/TypeDescriptors/PrimitiveDescriptor.cs","lineNumber":21,"sourceCode":"\nusing System.Reflection;\nusing Stride.Core.Yaml.Serialization;\n\nnamespace Stride.Core.Reflection;\n\n/// <summary>\n/// Describes a descriptor for a primitive (bool, char, sbyte, byte, int, uint, long, ulong, float, double, decimal, string, DateTime).\n/// </summary>\npublic class PrimitiveDescriptor : ObjectDescriptor\n{\n    private static readonly List<IMemberDescriptor> EmptyMembers = [];\n    private readonly Dictionary<string, object?> enumRemap;\n\n    public PrimitiveDescriptor(ITypeDescriptorFactory factory, Type type, bool emitDefaultValues, IMemberNamingConvention namingConvention)\n        : base(factory, type, emitDefaultValues, namingConvention)\n    {\n        if (!IsPrimitive(type))\n            throw new ArgumentException(\"Type [{0}] is not a primitive\");\n        enumRemap = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);\n\n        // Handle remap for enum items\n        if (type.IsEnum)\n        {\n            foreach (var member in type.GetFields(BindingFlags.Public | BindingFlags.Static))\n            {\n                foreach (var attribute in AttributeRegistry.GetAttributes(member))\n                {\n                    if (attribute is DataAliasAttribute aliasAttribute)\n                    {\n                        enumRemap[aliasAttribute.Name] = member.GetValue(null);\n                    }\n                }\n            }\n        }\n    }\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Reflection/TypeDescriptors/PrimitiveDescriptor.cs#L3-L39","documentation":"PrimitiveDescriptor's constructor asserts IsPrimitive(type) — the set of primitive/enum/string types the descriptor supports — and throws ArgumentException 'Type [{0}] is not a primitive' when handed any other type. The '{0}' placeholder is not expanded (no string.Format), so the message shows the literal placeholder. Descriptors are normally created by TypeDescriptorFactory, which should route only primitives here.","triggerScenarios":"Constructing PrimitiveDescriptor directly with a non-primitive type (custom class, struct, interface, decimal in some definitions) or a factory misrouting a complex type to the primitive branch.","commonSituations":"Custom descriptor factories or serializer extensions adding descriptors for new types; tests instantiating PrimitiveDescriptor with arbitrary types; version changes where a type's classification changed (e.g. type moved out of the primitive set).","solutions":["Verify the type before construction (check it is a primitive, enum, or string).","Route non-primitive types to ObjectDescriptor via TypeDescriptorFactory.","Fix the factory dispatch predicate so only supported primitives reach PrimitiveDescriptor."],"exampleFix":"// before\nvar d = new PrimitiveDescriptor(factory, typeof(MyClass), false, convention);\n// after\nvar d = new ObjectDescriptor(factory, typeof(MyClass), false, convention);","handlingStrategy":"validation","validationCode":"bool ok = type.IsPrimitive || type.IsEnum || type == typeof(string) || type == typeof(decimal) || type == typeof(object) || type == typeof(Guid) || type == typeof(TimeSpan);\nif (!ok) throw new InvalidOperationException($\"{type} is not a primitive supported by PrimitiveDescriptor\");","typeGuard":"static bool IsSupportedPrimitive(Type t) => t.IsPrimitive || t.IsEnum || t == typeof(string);","tryCatchPattern":"try { return new PrimitiveDescriptor(factory, type, emit, conv); }\ncatch (ArgumentException) { return TypeDescriptorFactory.Default.FindDescriptor(type); }","preventionTips":["Only instantiate PrimitiveDescriptor for primitives, enums, and string.","Prefer TypeDescriptorFactory.FindDescriptor over manual descriptor construction.","Match your IsPrimitive check to the library's actual supported set before constructing."],"tags":["reflection","constructor","primitive-type","csharp"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}