JamesNK/Newtonsoft.Json · error · JsonSerializationException
Could not find type '{0}' in assembly '{1}'.
Error message
Could not find type '{0}' in assembly '{1}'. What it means
The assembly named in $type loaded successfully, but the type name could not be resolved. For generic type names (containing a backtick), Json.NET attempts manual parsing of the generic arguments via GetGenericTypeFromTypeName; if that throws, the exception is wrapped and rethrown as a JsonSerializationException (line 115). This indicates a malformed generic $type string or a generic argument whose own assembly/type is unavailable.
Source
Thrown at Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs:115
if (assembly == null)
{
throw new JsonSerializationException("Could not load assembly '{0}'.".FormatWith(CultureInfo.InvariantCulture, assemblyName));
}
Type? type = assembly.GetType(typeName);
if (type == null)
{
// if generic type, try manually parsing the type arguments for the case of dynamically loaded assemblies
// example generic typeName format: System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
if (StringUtils.IndexOf(typeName, '`') >= 0)
{
try
{
type = GetGenericTypeFromTypeName(typeName, assembly);
}
catch (Exception ex)
{
throw new JsonSerializationException("Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeName, assembly.FullName), ex);
}
}
if (type == null)
{
throw new JsonSerializationException("Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeName, assembly.FullName));
}
}
return type;
}
else
{
return Type.GetType(typeName)!;
}
}
private Type? GetGenericTypeFromTypeName(string typeName, Assembly assembly)View on GitHub (pinned to 4f73e74372)
Solutions
- Validate/sanitize the $type string before deserialization; reject payloads with malformed generic type names.
- Use a custom SerializationBinder to normalize known generic type names to the runtime types available.
- Ensure all assemblies referenced by the generic arguments are loaded.
- Avoid TypeNameHandling.All/Auto for untrusted or cross-version JSON.
Example fix
// before
var obj = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
// json has $type = "System.Collections.Generic.Dictionary`2[[Bad.Arg, NoAssembly],[System.String, mscorlib]]"
// after
var settings = new JsonSerializerSettings {
TypeNameHandling = TypeNameHandling.Auto,
SerializationBinder = new CustomBinder()
};
// CustomBinder.BindToType parses typeName defensively and rejects/remaps unknown generics Defensive patterns
Strategy: validation
Validate before calling
public sealed class StrictBinder : DefaultSerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
if (typeName.IndexOf('`') >= 0)
{
// only allow a curated set of generic definitions
var allowed = new[] { typeof(List<>), typeof(Dictionary<,>) };
// parse defensively; reject anything not on the allowlist
}
return base.BindToType(assemblyName, typeName);
}
} Type guard
static bool IsWellFormedGenericTypeName(string typeName)
{
var bt = typeName.IndexOf('`');
if (bt < 0) return true;
return typeName.IndexOf('[', bt) >= 0 && typeName.EndsWith("]");
} Try / catch
try { return JsonConvert.DeserializeObject(json, type, settings); }
catch (JsonSerializationException ex) when (ex.Message.StartsWith("Could not find type") && ex.InnerException != null)
{
// generic type parse failed; reject payload or remap via binder
} Prevention
- Validate $type strings before honoring them; reject malformed generic names.
- Use a SerializationBinder allowlist that only permits known generic definitions.
- Avoid TypeNameHandling on untrusted or cross-version JSON.
When it happens
Trigger: Deserializing a $type like "System.Collections.Generic.Dictionary`2[[...missing...],[...]]" whose generic argument string is malformed or references an unloaded assembly/type.
Common situations: Cross-version generic type names where an argument's assembly strong-name no longer matches, or hand-crafted/corrupted JSON $type values.
Related errors
- Could not load assembly '{0}'.
- Unexpected BsonType value: {0}
- Unable to read beyond the end of the stream.
- Expected Bytes but got {0}.
- No object created.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/ae49da9b37016bbd.
Report an issue: GitHub.