stride3d/stride · error · InvalidOperationException

The type of collection does not have a parameterless…

Error message

The type of collection does not have a parameterless constructor.

What it means

CollectionWithIdsSerializer.CreatEmptyContainer builds a closed generic CollectionWithItemIds<T> over the target collection's element type; it demands that constructed type to have a parameterless constructor so it can instantiate the deserialization container. If CollectionWithItemIds<T> (or the reflected construction) lacks an accessible parameterless ctor, it throws InvalidOperationException.

Solutions

  1. Keep a public parameterless constructor on CollectionWithItemIds<T> (restore it if removed)
  2. Fix the element type resolution so the generic is built over the correct concrete type
  3. Check whether linking/AOT trimming removed the ctor and preserve it (DynamicallyAccessedMembers/linker XML)
  4. Verify you are not passing a custom collection type into the asset pipeline that bypasses the expected container

Example fix

// before (CollectionWithItemIds.cs)
public CollectionWithItemIds(int capacity) { ... } // no parameterless ctor
// after
public CollectionWithItemIds() { }
public CollectionWithItemIds(int capacity) { ... }
Defensive patterns

Strategy: validation

Validate before calling

var elemType = GetCollectionElementType(myCollectionType);
var containerType = typeof(CollectionWithItemIds<>).MakeGenericType(elemType);
if (containerType.GetConstructor(Type.EmptyTypes) == null)
    throw new InvalidOperationException($"{containerType} lost its parameterless ctor; fix before asset serialization");

Try / catch

try { SerializeAssets(stream, asset); }
catch (InvalidOperationException ex) when (ex.Message.Contains("parameterless constructor"))
{
    Log.Error("Serializer container type broken: {Message}", ex.Message);
    throw;
}

Prevention

When it happens

Trigger: Serializing/deserializing an asset collection whose element type makes CollectionWithItemIds<T> resolve to a type without a public parameterless constructor; fork modifications removing the default ctor; generic type resolution producing an unexpected element type (e.g. abstract/interface element without concrete container).

Common situations: Custom asset types with unusual element types in item collections; modified Stride source where CollectionWithItemIds<T> gained ctor parameters; reflection/AOT trimming scenarios stripping the constructor.

Related errors


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

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/Yaml/CollectionWithIdsSerializer.cs:104

            if (!identifier.TryGet(i, out var id))
            {
                id = ItemId.New();
                identifier.Add(i, id);
            }
            instance.Add(id, item);
            ++i;
        }

        return instance;
    }

    /// <inheritdoc/>
    protected override IDictionary CreatEmptyContainer(ITypeDescriptor descriptor)
    {
        var collectionDescriptor = (CollectionDescriptor)descriptor;
        var type = typeof(CollectionWithItemIds<>).MakeGenericType(collectionDescriptor.ElementType);
        if (type.GetConstructor(Type.EmptyTypes) == null)
            throw new InvalidOperationException("The type of collection does not have a parameterless constructor.");
        return (IDictionary)Activator.CreateInstance(type)!;
    }

    /// <inheritdoc/>
    protected override void TransformAfterDeserialization(IDictionary container, ITypeDescriptor targetDescriptor, object targetCollection, ICollection<ItemId>? deletedItems = null)
    {
        var collectionDescriptor = (CollectionDescriptor)targetDescriptor;
        var type = typeof(CollectionWithItemIds<>).MakeGenericType(collectionDescriptor.ElementType);
        if (!type.IsInstanceOfType(container))
            throw new InvalidOperationException("The given container does not match the expected type.");
        var identifier = CollectionItemIdHelper.GetCollectionItemIds(targetCollection);
        identifier.Clear();

        // The collection may contain some initial data from its containing instance's ctor,
        // let's replace the existing data with the data we have serialized
        collectionDescriptor.Clear(targetCollection);

        var i = 0;

View on GitHub (pinned to 96fad776d2)