{"record":{"id":"0d0ab7d84b73648e","repo":"stride3d/stride","slug":"serialization-of-nested-types-referencing-parent-s-generic","errorCode":null,"errorMessage":"Serialization of nested types referencing parent's generic parameters is not currently supported. [Nested type={0} Parent={1}]","messagePattern":"Serialization of nested types referencing parent's generic parameters is not currently supported\\. \\[Nested type=(.+?) Parent=(.+?)\\]","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs","lineNumber":452,"sourceCode":"                IsPublic = type.HasGenericParameters,\n                UseClassDataSerializer = useClassDataSerializer,\n                SerializableTypeInfo = serializableTypeInfo,\n            };\n            PendingSerializers.Add(descriptor);\n        }\n\n        serializableTypeInfo.IsGeneratedSerializer = true;\n\n        return (serializableTypeInfo, descriptor);\n    }\n\n    public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = \"Default\")\n    {\n        // Check if declaring type is generics\n        var resolvedType = dataType.Resolve();\n        if (resolvedType?.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters))\n        {\n            throw new NotSupportedException(string.Format(\"Serialization of nested types referencing parent's generic parameters is not currently supported. \" +\n                                                          \"[Nested type={0} Parent={1}]\", resolvedType.FullName, resolvedType.DeclaringType));\n        }\n\n        var profileInfo = GetSerializableTypes(profile);\n\n        if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var currentValue))\n        {\n            // TODO: Doesn't work in some generic case\n            if (currentValue.Mode != serializableTypeInfo.Mode)\n                throw new InvalidOperationException(string.Format(\"Incompatible serializer found for same type in different assemblies for {0}\", dataType.ConvertCSharp()));\n            return;\n        }\n\n        // Check that we don't simply try to add the same serializer than Default profile (optimized)\n        if (profile != \"Default\" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out var defaultValue))\n        {\n            if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName)\n            {","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs#L434-L470","documentation":"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.","triggerScenarios":"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; } }).","commonSituations":"Declaring a data contract nested inside a generic class; moving a serializable class inside a generic wrapper during refactoring.","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"],"exampleFix":"// before\npublic class Container<T>\n{\n    public class Item { public T Value; } // nested, references T\n}\n// after\npublic class ContainerItem<T>\n{\n    public T Value;\n}\npublic class Container<T> { ... }","handlingStrategy":"validation","validationCode":"static void EnsureNotGenericNested(Type t)\n{\n    if (t.IsNested && (t.ContainsGenericParameters || t.DeclaringType.ContainsGenericParameters))\n        throw new InvalidOperationException($\"{t.FullName} must not be nested in a generic type\");\n}","typeGuard":"static bool IsUnsupportedNestedGeneric(Type t) =>\n    t.IsNested && (t.ContainsGenericParameters || t.DeclaringType.ContainsGenericParameters);","tryCatchPattern":null,"preventionTips":["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"],"tags":["serialization","generics","unsupported","nested-types"],"backgroundTag":"unsupported-operation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}