stride3d/stride · error · NotSupportedException
Serialization of nested types referencing parent's generic…
Error message
Serialization of nested types referencing parent's generic parameters is not currently supported. [Nested type={0} Parent={1}] What it means
AddSerializableType rejects nested types that reference their declaring (parent) type's generic parameters, because the assembly processor cannot generate serializers for such open-nested generics. This is an explicit NotSupported limitation of the codegen.
Solutions
- Move the nested type out of the generic parent to top-level scope
- Remove the dependency on the parent's generic parameters (replace T with a concrete type)
- If generic behavior is needed, make the nested type itself generic and use a dedicated DataSerializer
- Wrap the data in a non-generic container type instead
Example fix
// before
public class Container<T>
{
public class Item { public T Value; } // nested, references T
}
// after
public class ContainerItem<T>
{
public T Value;
}
public class Container<T> { ... } Defensive patterns
Strategy: validation
Validate before calling
static void EnsureNotGenericNested(Type t)
{
if (t.IsNested && (t.ContainsGenericParameters || t.DeclaringType.ContainsGenericParameters))
throw new InvalidOperationException($"{t.FullName} must not be nested in a generic type");
} Type guard
static bool IsUnsupportedNestedGeneric(Type t) =>
t.IsNested && (t.ContainsGenericParameters || t.DeclaringType.ContainsGenericParameters); Prevention
- Never nest data contracts inside generic classes
- Keep serializable types top-level and closed (no open generics)
- Refactor nested types out of generic parents before adding serialization
When it happens
Trigger: Any of ResolveSerializer/FindSerializerInfo/ProcessDataSerializerAttribute etc. calls AddSerializableType with a nested type whose own or whose declaring type HasGenericParameters is true (e.g. class Outer<T> { class Inner { public T Value; } }).
Common situations: Declaring a data contract nested inside a generic class; moving a serializable class inside a generic wrapper during refactoring.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported generic resolution.
- Incompatible serializer found for same type in different…
- Could not find serializer for generic dependent type
- Can't deduce data serializer type for generic types.
- Legacy (pre-4.2) ServiceWire deserialize of
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/0d0ab7d84b73648e.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs:452
IsPublic = type.HasGenericParameters,
UseClassDataSerializer = useClassDataSerializer,
SerializableTypeInfo = serializableTypeInfo,
};
PendingSerializers.Add(descriptor);
}
serializableTypeInfo.IsGeneratedSerializer = true;
return (serializableTypeInfo, descriptor);
}
public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = "Default")
{
// Check if declaring type is generics
var resolvedType = dataType.Resolve();
if (resolvedType?.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters))
{
throw new NotSupportedException(string.Format("Serialization of nested types referencing parent's generic parameters is not currently supported. " +
"[Nested type={0} Parent={1}]", resolvedType.FullName, resolvedType.DeclaringType));
}
var profileInfo = GetSerializableTypes(profile);
if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var currentValue))
{
// TODO: Doesn't work in some generic case
if (currentValue.Mode != serializableTypeInfo.Mode)
throw new InvalidOperationException(string.Format("Incompatible serializer found for same type in different assemblies for {0}", dataType.ConvertCSharp()));
return;
}
// Check that we don't simply try to add the same serializer than Default profile (optimized)
if (profile != "Default" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var defaultValue))
{
if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName)
{View on GitHub (pinned to 96fad776d2)