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

  1. Verify the type before construction (check it is a primitive, enum, or string).
  2. Route non-primitive types to ObjectDescriptor via TypeDescriptorFactory.
  3. 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

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


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)