stride3d/stride · error · InvalidOperationException

Unsupported generic resolution.

Error message

Unsupported generic resolution.

What it means

ResolveGenericsVisitor closes generic types during serialization processing; after visiting, Process checks result.ContainsGenericParameter() and throws this InvalidOperationException if the type still has open generic parameters, meaning the visitor could not produce a closed type.

Solutions

  1. Ensure serialized member types are fully closed (List<int> not List<T>)
  2. Avoid declaring open generic fields/properties on classes processed for serialization
  3. Provide concrete instantiations for all generic parameters used in serializable contracts
  4. If the pattern is legitimate, report as an AssemblyProcessor limitation and restructure the contract

Example fix

// before
class MyComponent<T> : SyncScript<T> { public T Data; } // open generic member
// after
class MyComponent : SyncScript<MyComponent.State> { public State Data; } // closed type
Defensive patterns

Strategy: validation

Validate before calling

bool IsClosed(Type t) => !t.ContainsGenericParameters;
if (!IsClosed(memberType)) throw new InvalidOperationException("Serialize member types must be closed generics");

Type guard

bool IsClosedGeneric(Type t) => !t.ContainsGenericParameters;

Try / catch

catch (InvalidOperationException ex) when (ex.Message == "Unsupported generic resolution.")
{
    // locate open generic member in the data contract and close it
}

Prevention

When it happens

Trigger: Serializing a data contract whose type (or member type) is generic and cannot be fully closed by the generic type mapping — e.g. a generic class member or unbound generic parameter reaching the processor.

Common situations: Declaring generic fields/properties on serializable components; open generic types (e.g. typeof(List<>)) in serialized contracts; nested generics spanning assemblies the mapping doesn't cover.

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/dd62120f44da889d. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.AssemblyProcessor/ResolveGenericsVisitor.cs:63

        while (parentContext != null)
        {
            var resolvedType = parentContext.Resolve();
            for (int i = 0; i < resolvedType.GenericParameters.Count; ++i)
            {
                var genericParameter = parentContext.GetElementType().Resolve().GenericParameters[i];
                genericTypeMapping.Add(genericParameter, genericInstanceTypeContext.GenericArguments[i]);
            }
            parentContext = parentContext.Resolve().BaseType;
            if (parentContext is GenericInstanceType)
                genericInstanceTypeContext = parentContext as GenericInstanceType;
        }

        var visitor = new ResolveGenericsVisitor(genericTypeMapping);
        var result = visitor.VisitDynamic(type);

        // Make sure type is closed now
        if (result.ContainsGenericParameter())
            throw new InvalidOperationException("Unsupported generic resolution.");

        return result;
    }

    /// <summary>
    /// Creates a visitor that maps generic parameters from <paramref name="source"/> to <paramref name="target"/>.
    /// Returns null if the source has no generic parameters.
    /// </summary>
    public static ResolveGenericsVisitor? FromMapping(IGenericParameterProvider source, IGenericParameterProvider target)
    {
        if (source.GenericParameters.Count == 0)
            return null;

        var mapping = new Dictionary<TypeReference, TypeReference>();
        for (int i = 0; i < source.GenericParameters.Count; i++)
            mapping[source.GenericParameters[i]] = target.GenericParameters[i];
        return new ResolveGenericsVisitor(mapping);
    }

View on GitHub (pinned to 96fad776d2)