{"record":{"id":"c46dbb8ef724dc50","repo":"JamesNK/Newtonsoft.Json","slug":"serialization-error-callback-1-in-type-0-m","errorCode":null,"errorMessage":"Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.","messagePattern":"Serialization Error Callback '(.+?)' in type '(.+?)' must have two parameters of type '(.+?)' and '(.+?)'\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs","lineNumber":1339,"sourceCode":"            {\n                throw new JsonException(\"Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.\".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType!), method));\n            }\n\n            if (method.IsVirtual)\n            {\n                throw new JsonException(\"Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.\".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType!), attributeType));\n            }\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())","sourceCodeStart":1321,"sourceCodeEnd":1357,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs#L1321-L1357","documentation":"An [OnError] callback must have exactly two parameters: a StreamingContext followed by an ErrorContext. IsValidCallback verifies parameter count and types and throws a JsonException (line 1339) otherwise. The error callback receives the serialization context and the error context so the handler can inspect and decide whether to swallow the error.","triggerScenarios":"An [OnError] method with zero, one, or three+ parameters, or with parameters of the wrong types (e.g. Exception instead of ErrorContext).","commonSituations":"Declaring an error handler with a single 'Exception' parameter by analogy with try/catch, or forgetting the StreamingContext parameter.","solutions":["Give the [OnError] method the signature 'void M(StreamingContext context, ErrorContext errorContext)'.","Decide whether to handle the error by setting errorContext.Handled = true inside the callback."],"exampleFix":"// before\npublic class Model {\n    [OnError]\n    internal void OnError(Exception ex) {} // wrong signature -> throws\n}\n\n// after\npublic class Model {\n    [OnError]\n    internal void OnError(StreamingContext context, ErrorContext errorContext) {\n        errorContext.Handled = true;\n    }\n}","handlingStrategy":"validation","validationCode":"foreach (var m in typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(m => m.IsDefined(typeof(OnErrorAttribute), false)))\n{\n    var ps = m.GetParameters();\n    if (ps.Length != 2 || ps[0].ParameterType != typeof(StreamingContext) || ps[1].ParameterType != typeof(ErrorContext))\n        throw new InvalidOperationException($\"OnError method {m.Name} must be (StreamingContext, ErrorContext).\");\n}","typeGuard":"static bool OnErrorSignatureIsValid(MethodInfo m)\n{\n    if (!m.IsDefined(typeof(OnErrorAttribute), false)) return true;\n    var ps = m.GetParameters();\n    return ps.Length == 2 && ps[0].ParameterType == typeof(StreamingContext) && ps[1].ParameterType == typeof(ErrorContext);\n}","tryCatchPattern":"try { JsonConvert.DeserializeObject<T>(json); }\ncatch (JsonException ex) when (ex.Message.Contains(\"Serialization Error Callback\") && ex.Message.Contains(\"two parameters\"))\n{\n    // fix the OnError signature to (StreamingContext, ErrorContext)\n}","preventionTips":["OnError methods must take (StreamingContext context, ErrorContext errorContext).","Set errorContext.Handled = true to swallow specific errors."],"tags":["callback","error-handling","attribute-validation","contract-resolution"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}