{"record":{"id":"db94ff3f4502403d","repo":"JamesNK/Newtonsoft.Json","slug":"serialization-callback-1-in-type-0-must-ha","errorCode":null,"errorMessage":"Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.","messagePattern":"Serialization Callback '(.+?)' in type '(.+?)' must have a single parameter of type '(.+?)'\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs","lineNumber":1346,"sourceCode":"            }\n\n            if (method.ReturnType != typeof(void))\n            {\n                throw new JsonException(\"Serialization Callback '{1}' in type '{0}' must return void.\".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType!), method));\n            }\n\n            if (attributeType == typeof(OnErrorAttribute))\n            {\n                if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext))\n                {\n                    throw new JsonException(\"Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.\".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType!), method, typeof(StreamingContext), typeof(ErrorContext)));\n                }\n            }\n            else\n            {\n                if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext))\n                {\n                    throw new JsonException(\"Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.\".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType!), method, typeof(StreamingContext)));\n                }\n            }\n\n            prevAttributeType = attributeType;\n\n            return true;\n        }\n\n        internal static string GetClrTypeFullName(Type type)\n        {\n            if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters())\n            {\n                return type.FullName!;\n            }\n\n            return \"{0}.{1}\".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name);\n        }\n","sourceCodeStart":1328,"sourceCodeEnd":1364,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs#L1328-L1364","documentation":"Serialization lifecycle callbacks ([OnSerializing], [OnSerialized], [OnDeserializing], [OnDeserialized]) must take exactly one parameter of type StreamingContext. IsValidCallback checks the parameter count and type and throws a JsonException (line 1346) otherwise. The streaming context is the only argument these hooks accept.","triggerScenarios":"A callback method declared with no parameters, or with parameters of a type other than StreamingContext (e.g. the model type itself).","commonSituations":"Declaring a parameterless callback, or passing the deserialized object as a parameter by mistake.","solutions":["Give the callback the signature 'void M(StreamingContext context)'.","Access the object being serialized via 'this' inside an instance method rather than as a parameter."],"exampleFix":"// before\npublic class Model {\n    [OnDeserialized]\n    internal void OnDeserialized() {} // missing parameter -> throws\n}\n\n// after\npublic class Model {\n    [OnDeserialized]\n    internal void OnDeserialized(StreamingContext context) {}\n}","handlingStrategy":"validation","validationCode":"var attrs = new[] { typeof(OnSerializingAttribute), typeof(OnSerializedAttribute), typeof(OnDeserializingAttribute), typeof(OnDeserializedAttribute) };\nforeach (var m in typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))\n{\n    if (attrs.Any(a => m.IsDefined(a, false)))\n    {\n        var ps = m.GetParameters();\n        if (ps.Length != 1 || ps[0].ParameterType != typeof(StreamingContext))\n            throw new InvalidOperationException($\"Callback {m.Name} must take a single StreamingContext.\");\n    }\n}","typeGuard":"static bool LifecycleCallbackSignatureIsValid(MethodInfo m)\n{\n    var attrs = new[] { typeof(OnSerializingAttribute), typeof(OnSerializedAttribute), typeof(OnDeserializingAttribute), typeof(OnDeserializedAttribute) };\n    if (!attrs.Any(a => m.IsDefined(a, false))) return true;\n    var ps = m.GetParameters();\n    return ps.Length == 1 && ps[0].ParameterType == typeof(StreamingContext);\n}","tryCatchPattern":"try { JsonConvert.DeserializeObject<T>(json); }\ncatch (JsonException ex) when (ex.Message.Contains(\"must have a single parameter of type\"))\n{\n    // add/fix the single StreamingContext parameter\n}","preventionTips":["Lifecycle callbacks must take exactly one StreamingContext parameter.","Access the object via 'this' in instance methods, not via parameters."],"tags":["callback","attribute-validation","contract-resolution","parameter-validation"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}