JamesNK/Newtonsoft.Json · error · JsonException
Serialization Callback '{1}' in type '{0}' must have a singl
Error message
Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'. What it means
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.
Source
Thrown at Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs:1346
}
if (method.ReturnType != typeof(void))
{
throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType!), method));
}
if (attributeType == typeof(OnErrorAttribute))
{
if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext))
{
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)));
}
}
else
{
if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext))
{
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)));
}
}
prevAttributeType = attributeType;
return true;
}
internal static string GetClrTypeFullName(Type type)
{
if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters())
{
return type.FullName!;
}
return "{0}.{1}".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name);
}
View on GitHub (pinned to 4f73e74372)
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.
Example fix
// before
public class Model {
[OnDeserialized]
internal void OnDeserialized() {} // missing parameter -> throws
}
// after
public class Model {
[OnDeserialized]
internal void OnDeserialized(StreamingContext context) {}
} Defensive patterns
Strategy: validation
Validate before calling
var attrs = new[] { typeof(OnSerializingAttribute), typeof(OnSerializedAttribute), typeof(OnDeserializingAttribute), typeof(OnDeserializedAttribute) };
foreach (var m in typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
if (attrs.Any(a => m.IsDefined(a, false)))
{
var ps = m.GetParameters();
if (ps.Length != 1 || ps[0].ParameterType != typeof(StreamingContext))
throw new InvalidOperationException($"Callback {m.Name} must take a single StreamingContext.");
}
} Type guard
static bool LifecycleCallbackSignatureIsValid(MethodInfo m)
{
var attrs = new[] { typeof(OnSerializingAttribute), typeof(OnSerializedAttribute), typeof(OnDeserializingAttribute), typeof(OnDeserializedAttribute) };
if (!attrs.Any(a => m.IsDefined(a, false))) return true;
var ps = m.GetParameters();
return ps.Length == 1 && ps[0].ParameterType == typeof(StreamingContext);
} Try / catch
try { JsonConvert.DeserializeObject<T>(json); }
catch (JsonException ex) when (ex.Message.Contains("must have a single parameter of type"))
{
// add/fix the single StreamingContext parameter
} Prevention
- Lifecycle callbacks must take exactly one StreamingContext parameter.
- Access the object via 'this' in instance methods, not via parameters.
When it happens
Trigger: A callback method declared with no parameters, or with parameters of a type other than StreamingContext (e.g. the model type itself).
Common situations: Declaring a parameterless callback, or passing the deserialized object as a parameter by mistake.
Related errors
- Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '
- Invalid Callback. Method '{3}' in type '{2}' has both '{0}'
- Virtual Method '{0}' of type '{1}' cannot be marked with '{2
- Serialization Callback '{1}' in type '{0}' must return void.
- Serialization Error Callback '{1}' in type '{0}' must have t
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/db94ff3f4502403d.
Report an issue: GitHub.