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
- Keep a public parameterless constructor on CollectionWithItemIds<T> (restore it if removed)
- Fix the element type resolution so the generic is built over the correct concrete type
- Check whether linking/AOT trimming removed the ctor and preserve it (DynamicallyAccessedMembers/linker XML)
- 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
- Never remove the default constructor from CollectionWithItemIds<T>
- Add a reflection test asserting the container types have parameterless ctors
- Configure trimmer/linker preserve rules for serializer container types
- Keep element types concrete and consistent with the serializer's expectations
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
- The type of dictionary does not have a parameterless…
- Event handlers can't be added or removed after the…
- RoutingSerializer expected in the chain of serializers
- The given container does not match the expected type.
- The order of the Asset.Id property must be lower than the…
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)