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

  1. Ensure the type resolves to one of the standard contract types (use the default DefaultContractResolver).
  2. If a custom IContractResolver is in use, make it return standard contract types (JsonObjectContract, JsonArrayContract, JsonDictionaryContract, JsonPrimitiveContract, JsonLinqContract, JsonStringContract, JsonISerializableContract).
  3. 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

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


AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07). Data as JSON: /api/errors/cd6600ac28698b23. Report an issue: GitHub.