stride3d/stride · error · InvalidOperationException
The type of dictionary does not have a parameterless…
Error message
The type of dictionary does not have a parameterless constructor.
What it means
DictionaryWithIdsSerializer.CreatEmptyContainer constructs DictionaryWithItemIds<TKey,TValue> from the target dictionary's key/value types and requires a public parameterless constructor to instantiate it as the deserialization container. When the constructed generic type has no parameterless ctor, it throws InvalidOperationException, mirroring the collection-side guard.
Solutions
- Restore a public parameterless constructor on DictionaryWithItemIds<TKey,TValue>
- Fix the generic construction so key/value types match the intended concrete types
- Add linker/trimmer preservation for the parameterless constructor
- Ensure the asset member's declared dictionary type matches what the serializer expects
Example fix
// before (DictionaryWithItemIds.cs)
public DictionaryWithItemIds(IDictionary<TKey,TValue> source) { ... } // no parameterless ctor
// after
public DictionaryWithItemIds() { }
public DictionaryWithItemIds(IDictionary<TKey,TValue> source) { ... } Defensive patterns
Strategy: validation
Validate before calling
var kvTypes = GetDictionaryKVTypes(myDictionaryType);
var containerType = typeof(DictionaryWithItemIds<,>).MakeGenericType(kvTypes.KeyType, kvTypes.ValueType);
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("Dictionary serializer container broken: {Message}", ex.Message);
throw;
} Prevention
- Keep a public parameterless constructor on DictionaryWithItemIds<TKey,TValue>
- Add a reflection test asserting the container types have parameterless ctors
- Configure trimmer preserve rules for serializer container types in published builds
- Verify dictionary member key/value types resolve to the concrete types the serializer expects
When it happens
Trigger: Deserializing an asset whose dictionary member leads to DictionaryWithItemIds<TKey,TValue> lacking a default ctor; source modifications removing the default constructor; trimming/AOT stripping the constructor; wrong KeyType/ValueType resolution building an unexpected generic instantiation.
Common situations: Custom asset dictionary members with exotic key/value types; patched Stride source; IL trimming in published editor builds breaking reflection-based activation.
Related errors
- The type of collection 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/63dc1373844307a0.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets/Yaml/DictionaryWithIdsSerializer.cs:87
if (!identifier.TryGet(item.Key, out var id))
{
id = ItemId.New();
identifier.Add(item.Key, id);
}
var keyWithId = Activator.CreateInstance(keyWithIdType, id, item.Key)!;
instance.Add(keyWithId, item.Value);
}
return instance;
}
/// <inheritdoc/>
protected override IDictionary CreatEmptyContainer(ITypeDescriptor descriptor)
{
var dictionaryDescriptor = (DictionaryDescriptor)descriptor;
var type = typeof(DictionaryWithItemIds<,>).MakeGenericType(dictionaryDescriptor.KeyType, dictionaryDescriptor.ValueType);
if (type.GetConstructor(Type.EmptyTypes) == null)
throw new InvalidOperationException("The type of dictionary 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 dictionaryDescriptor = (DictionaryDescriptor)targetDescriptor;
var type = typeof(DictionaryWithItemIds<,>).MakeGenericType(dictionaryDescriptor.KeyType, dictionaryDescriptor.ValueType);
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
dictionaryDescriptor.Clear(targetCollection);
var enumerator = container.GetEnumerator();View on GitHub (pinned to 96fad776d2)