stride3d/stride · error · InvalidOperationException

The given container does not match the expected type.

Error message

The given container does not match the expected type.

What it means

After deserialization, CollectionWithIdsSerializer.TransformAfterDeserialization checks that the intermediate container is an instance of the expected closed generic CollectionWithItemIds<T> before copying item ids into the real collection. A mismatched container means the pipeline produced the wrong intermediate object, so it throws InvalidOperationException to prevent silently losing per-item ids.

Solutions

  1. Ensure the container passed through the chain is created by CreatEmptyContainer (CollectionWithItemIds<T>) and not replaced
  2. Remove or fix custom chained serializers that swap the intermediate container
  3. Verify target descriptor's element type matches the one used to build the container
  4. Revert to stock Stride serializer classes for asset collections

Example fix

// before
IDictionary container = new Dictionary<object, object>(); // wrong type
serializer.TransformObjectAfterRead(container, descriptor, target);
// after
var container = serializerInstance.CreateContainerForTest(descriptor); // produces CollectionWithItemIds<T>
serializer.TransformObjectAfterRead(container, descriptor, target);
Defensive patterns

Strategy: type-guard

Validate before calling

var expectedType = typeof(CollectionWithItemIds<>).MakeGenericType(elementType);
if (!expectedType.IsInstanceOfType(container))
    throw new InvalidOperationException($"Container must be {expectedType}, got {container?.GetType()}");

Type guard

static bool IsCollectionWithItemIdsOf(IDictionary? c, Type elementType) =>
    c != null && typeof(CollectionWithItemIds<>).MakeGenericType(elementType).IsInstanceOfType(c);

Try / catch

try { serializer.RunTransform(container, descriptor, target); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not match the expected type"))
{
    Log.Error("Intermediate collection container replaced in chain: {Message}", ex.Message);
    throw;
}

Prevention

When it happens

Trigger: A custom/derived serializer returning a different IDictionary container; chain changes so CreatEmptyContainer and TransformAfterDeserialization disagree; serializing an object whose descriptor element type changed between container creation and transform.

Common situations: Patched serializers or custom chained serializers for assets; version-skew between plugin code building containers and the Stride asset serializer; regression tests feeding hand-built dictionaries into the transform step.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

    }

    /// <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;
        var enumerator = container.GetEnumerator();
        while (enumerator.MoveNext())
        {
            collectionDescriptor.Add(targetCollection, enumerator.Value);
            if (targetDescriptor.Category == DescriptorCategory.Set)
            {
                identifier.Add(enumerator.Value!, (ItemId)enumerator.Key);
            }
            else
            {

View on GitHub (pinned to 96fad776d2)