stride3d/stride · error · ArgumentException

Value type for root objects are not supported

Error message

Value type for root objects are not supported

What it means

MemberPath.Apply performs a get/set action along a member path starting from a root object. Value-type roots are rejected with ArgumentException because the path mutations would operate on a boxed copy and be lost; only reference-type roots are supported.

Solutions

  1. Box the value into a class or use a class wrapper as the root before applying the path
  2. Operate on a field/property of a class that holds the struct instead of the struct itself
  3. Refactor the root data type to be a reference type

Example fix

// before
var path = new MemberPath(...);
path.Apply(myStruct, MemberPathAction.ValueSet, value);
// after
class Root { public MyStruct Data; }
path.Apply(root, MemberPathAction.ValueSet, value); // root is a class
Defensive patterns

Strategy: validation

Validate before calling

if (rootObject.GetType().IsValueType) throw new ArgumentException("MemberPath.Apply requires a reference-type root");

Type guard

bool canApply = !rootObject.GetType().IsValueType;

Try / catch

try { path.Apply(root, action, value); }
catch (ArgumentException) { /* root was a struct; wrap in a class */ }

Prevention

When it happens

Trigger: Calling Apply with a struct instance (e.g. a Vector3, or a struct wrapping data) as rootObject.

Common situations: Using MemberPath on struct-based data models or components that are structs; passing a struct after deserialization; test code (e.g. TestMyClass) exercising paths against value-type fixtures.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/722cafc3759ffd8d. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Reflection/MemberPath.cs:223

        ArgumentNullException.ThrowIfNull(descriptor);
        AddItem(new SetPathItem(descriptor, index));
    }

    /// <summary>
    /// Pops the last item from the current path.
    /// </summary>
    public void Pop()
    {
        if (items.Count > 0)
        {
            items.RemoveAt(items.Count - 1);
        }
    }

    public bool Apply(object rootObject, MemberPathAction actionType, object? value)
    {
        ArgumentNullException.ThrowIfNull(rootObject);
        if (rootObject.GetType().IsValueType) throw new ArgumentException("Value type for root objects are not supported", nameof(rootObject));
        if (actionType != MemberPathAction.ValueSet && actionType != MemberPathAction.CollectionAdd && value != null)
        {
            throw new ArgumentException("Value must be null for action != (MemberActionType.SetValue || MemberPathAction.CollectionAdd)");
        }

        if (items == null || items.Count == 0)
        {
            throw new InvalidOperationException("This instance doesn't contain any path. Use Push() methods to populate paths");
        }

        var lastItem = items[^1];
        switch (actionType)
        {
            case MemberPathAction.CollectionAdd:
                if (lastItem is not CollectionPathItem)
                {
                    throw new ArgumentException("Invalid path [{0}] for action [{1}]. Expecting last path to be a collection item".ToFormat(this, actionType));
                }

View on GitHub (pinned to 96fad776d2)