{"record":{"id":"90ba2ee9a24001de","repo":"stride3d/stride","slug":"not-sure-how-to-process-this-inherited-serializer","errorCode":null,"errorMessage":"Not sure how to process this inherited serializer","messagePattern":"Not sure how to process this inherited serializer","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs","lineNumber":384,"sourceCode":"            var genericInfo = new SerializableTypeInfo(parentInfo.SerializerType, true, parentInfo.Mode);\n            AddSerializableType(type, genericInfo);\n\n            if (!type.HasGenericParameters)\n            {\n                var genericArguments = parentType is GenericInstanceType git ? git.GenericArguments : [];\n                var actualSerializerType = InstantiateSerializerType(parentInfo.SerializerType, parentInfo.Mode, type, genericArguments);\n\n                var concreteInfo = new SerializableTypeInfo(actualSerializerType, true);\n                AddSerializableType(type, concreteInfo);\n\n                if (!generic)\n                    return concreteInfo;\n            }\n\n            return genericInfo;\n        }\n\n        throw new InvalidOperationException(\"Not sure how to process this inherited serializer\");\n    }\n\n    private (SerializableTypeInfo Info, SerializerDescriptor? Descriptor) CollectSerializer(TypeReference type)\n    {\n        var isLocal = type.Resolve().Module.Assembly == Assembly;\n\n        // Create a forward TypeReference for the serializer (the actual TypeDefinition is created later during code generation).\n        var className = SerializationHelpers.SerializerTypeName(type, false, true);\n        if (type.HasGenericParameters)\n            className += \"`\" + type.GenericParameters.Count;\n\n        var dataSerializerType = new TypeReference(\"Stride.Core.DataSerializers\", className, type.Module, isLocal ? Assembly.MainModule : type.Scope);\n\n        var mode = DataSerializerGenericMode.None;\n        if (type.HasGenericParameters)\n        {\n            mode = DataSerializerGenericMode.GenericArguments;\n","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.AssemblyProcessor/Serializers/CecilSerializerContext.cs#L366-L402","documentation":"FindInheritedSerializerInfo throws this when it cannot classify how an inherited serializer should be resolved: the type is neither a concrete serializer it could return nor a generic serializer it could process. It is an internal invariant check guarding the serializer-inheritance lookup.","triggerScenarios":"FindSerializerInfo delegates to FindInheritedSerializerInfo for a base/interface serializer lookup and the resolved SerializableTypeInfo matches neither the concrete nor the generic branch.","commonSituations":"Custom DataSerializer hierarchies that inherit in ways the processor does not model (e.g. open generic base serializers combined in unexpected ways); version upgrades changing SerializableTypeInfo modes.","solutions":["Inspect the serializer inheritance chain of the type and simplify it to a concrete DataSerializer","Make the serializer generic mode explicit via DataSerializerGenericMode on the serializer class","Register the serializer explicitly with [DataSerializer] on the data type instead of relying on inheritance","If in Stride source, extend FindInheritedSerializerInfo to handle the new inheritance shape"],"exampleFix":"// before\nclass MyListSerializer : DataSerializer<List<T>> {} // ambiguous inheritance\n// after\n[DataSerializerGenericMode(DataSerializerGenericMode.GenericArityAndArguments)]\nclass MyListSerializer<T> : DataSerializer<List<T>> {}","handlingStrategy":"try-catch","validationCode":"// Prefer explicitly registered serializers over inherited resolution:\nif (myType.GetCustomAttribute<DataSerializerAttribute>() == null &&\n    typeof(DataSerializer).IsAssignableFrom(mySerializerType) == false)\n    throw new InvalidOperationException(\"Register an explicit serializer for \" + myType.Name);","typeGuard":"static bool IsConcreteSerializer(Type t) =>\n    !t.IsAbstract && !t.ContainsGenericParameters && typeof(DataSerializer).IsAssignableFrom(t);","tryCatchPattern":"try { ProcessInheritedSerializer(type); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Not sure how to process this inherited serializer\"))\n{\n    logger.Warn($\"Falling back to explicit serializer registration for {type}\");\n    RegisterExplicitSerializer(type);\n}","preventionTips":["Avoid deep custom DataSerializer inheritance hierarchies","Prefer direct DataSerializer<T> derivation","Set DataSerializerGenericMode explicitly on generic serializers"],"tags":["serialization","assembly-processor","inheritance"],"backgroundTag":"internal-invariant-violation","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"}