JamesNK/Newtonsoft.Json · error · JsonException
Unexpected contract type: {0}
Error message
Unexpected contract type: {0} What it means
Thrown by JsonSchemaGenerator.GenerateInternal in the default case of the contract-type switch, meaning the resolved JsonContract has a ContractType value not handled by the schema generator (Object, Array, Primitive, String, Dictionary, Serializable, Dynamic, Linq). This indicates an unexpected or custom contract type.
Source
Thrown at Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs:387
CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false);
}
}
break;
#if HAVE_BINARY_SERIALIZATION
case JsonContractType.Serializable:
CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
CurrentSchema.Id = GetTypeId(type, false);
GenerateISerializableContract(type, (JsonISerializableContract)contract);
break;
#endif
#if HAVE_DYNAMIC
case JsonContractType.Dynamic:
#endif
case JsonContractType.Linq:
CurrentSchema.Type = JsonSchemaType.Any;
break;
default:
throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
}
}
return Pop().Schema;
}
private JsonSchemaType AddNullType(JsonSchemaType type, Required valueRequired)
{
if (valueRequired != Required.Always)
{
return type | JsonSchemaType.Null;
}
return type;
}
private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
{View on GitHub (pinned to 4f73e74372)
Solutions
- Ensure the type resolves to one of the standard contract types (use the default DefaultContractResolver).
- If a custom IContractResolver is in use, make it return standard contract types (JsonObjectContract, JsonArrayContract, JsonDictionaryContract, JsonPrimitiveContract, JsonLinqContract, JsonStringContract, JsonISerializableContract).
- Migrate schema generation to the dedicated Newtonsoft.Json.Schema package, which has broader contract support.
Example fix
// before gen.ContractResolver = new CustomResolverReturningUnknownContract(); gen.Generate(typeof(Foo)); // throws // after gen.ContractResolver = new DefaultContractResolver(); gen.Generate(typeof(Foo));
Defensive patterns
Strategy: validation
Validate before calling
static bool UsesStandardContract(Type type, IContractResolver resolver)
{
var ct = resolver.ResolveContract(type).ContractType;
return ct == JsonContractType.Object || ct == JsonContractType.Array ||
ct == JsonContractType.Primitive || ct == JsonContractType.String ||
ct == JsonContractType.Dictionary || ct == JsonContractType.Linq;
} Try / catch
try { generator.Generate(typeof(T)); }
catch (JsonException ex) when (ex.Message.StartsWith("Unexpected contract type"))
{ /* custom resolver returned a non-standard contract; switch to default resolver */ } Prevention
- Ensure custom IContractResolver implementations return standard JsonContract types.
- Use DefaultContractResolver when generating schemas.
- Migrate to the Newtonsoft.Json.Schema package for broader support.
When it happens
Trigger: Generating a schema for a type whose resolved contract is an uncommon or custom JsonContract subclass whose ContractType is outside the handled set, or a contract returned by a custom IContractResolver that fabricates a novel contract type.
Common situations: Using a custom IContractResolver that returns a non-standard JsonContract; a third-party contract type the generator was never taught; version mismatch between Newtonsoft.Json contract types and the schema generator; feeding a dynamically-built contract.
Related errors
- Unresolved circular reference for type '{0}'. Explicitly def
- Could not resolve schema reference '{0}'.
- Property {0} has already been defined in schema.
- Invalid JSON schema type: {0}
- Newtonsoft.Json serialization is not compatible with trimmin
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/cd6600ac28698b23.
Report an issue: GitHub.