stride3d/stride · error · ArgumentException
Type [ ] is not a primitive
Error message
Type [{0}] is not a primitive What it means
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.
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.
Example fix
// before var d = new PrimitiveDescriptor(factory, typeof(MyClass), false, convention); // after var d = new ObjectDescriptor(factory, typeof(MyClass), false, convention);
Defensive patterns
Strategy: validation
Validate before calling
bool ok = type.IsPrimitive || type.IsEnum || type == typeof(string) || type == typeof(decimal) || type == typeof(object) || type == typeof(Guid) || type == typeof(TimeSpan);
if (!ok) throw new InvalidOperationException($"{type} is not a primitive supported by PrimitiveDescriptor"); Type guard
static bool IsSupportedPrimitive(Type t) => t.IsPrimitive || t.IsEnum || t == typeof(string);
Try / catch
try { return new PrimitiveDescriptor(factory, type, emit, conv); }
catch (ArgumentException) { return TypeDescriptorFactory.Default.FindDescriptor(type); } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Type [ ] is not a primitive
- The associated asset type does not have a public…
- The type of collection does not have a parameterless…
- The type of dictionary does not have a parameterless…
- Invalid assembly path. Doesn't contain directory information
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/5dda5d31ac2a126d.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Reflection/TypeDescriptors/PrimitiveDescriptor.cs:21
using System.Reflection;
using Stride.Core.Yaml.Serialization;
namespace Stride.Core.Reflection;
/// <summary>
/// Describes a descriptor for a primitive (bool, char, sbyte, byte, int, uint, long, ulong, float, double, decimal, string, DateTime).
/// </summary>
public class PrimitiveDescriptor : ObjectDescriptor
{
private static readonly List<IMemberDescriptor> EmptyMembers = [];
private readonly Dictionary<string, object?> enumRemap;
public PrimitiveDescriptor(ITypeDescriptorFactory factory, Type type, bool emitDefaultValues, IMemberNamingConvention namingConvention)
: base(factory, type, emitDefaultValues, namingConvention)
{
if (!IsPrimitive(type))
throw new ArgumentException("Type [{0}] is not a primitive");
enumRemap = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
// Handle remap for enum items
if (type.IsEnum)
{
foreach (var member in type.GetFields(BindingFlags.Public | BindingFlags.Static))
{
foreach (var attribute in AttributeRegistry.GetAttributes(member))
{
if (attribute is DataAliasAttribute aliasAttribute)
{
enumRemap[aliasAttribute.Name] = member.GetValue(null);
}
}
}
}
}
View on GitHub (pinned to 96fad776d2)