JamesNK/Newtonsoft.Json · error · JsonSerializationException

Null collection of serializable members returned.

Error message

Null collection of serializable members returned.

What it means

CreateProperties calls the virtual GetSerializableMembers and throws a JsonSerializationException (line 1376) if it returns null. An empty list is acceptable; null is not, because the property-building loop would fail. This is a contract for anyone overriding GetSerializableMembers in a custom contract resolver.

Source

Thrown at Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs:1376

            {
                return type.FullName!;
            }

            return "{0}.{1}".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name);
        }

        /// <summary>
        /// Creates properties for the given <see cref="JsonContract"/>.
        /// </summary>
        /// <param name="type">The type to create properties for.</param>
        /// /// <param name="memberSerialization">The member serialization mode for the type.</param>
        /// <returns>Properties for the given <see cref="JsonContract"/>.</returns>
        protected virtual IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            List<MemberInfo> members = GetSerializableMembers(type);
            if (members == null)
            {
                throw new JsonSerializationException("Null collection of serializable members returned.");
            }

            DefaultJsonNameTable nameTable = GetNameTable();

            JsonPropertyCollection properties = new JsonPropertyCollection(type);

            foreach (MemberInfo member in members)
            {
                JsonProperty property = CreateProperty(member, memberSerialization);

                if (property != null)
                {
                    // nametable is not thread-safe for multiple writers
                    lock (nameTable)
                    {
                        property.PropertyName = nameTable.Add(property.PropertyName!);
                    }

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Return an empty list (e.g. 'return new List<MemberInfo>();') instead of null from the override.
  2. If you intended to skip property creation, return an empty collection rather than null.

Example fix

// before
protected override IList<MemberInfo> GetSerializableMembers(Type objectType) {
    var members = base.GetSerializableMembers(objectType).Where(Keep);
    return members.Any() ? members.ToList() : null; // throws
}

// after
protected override IList<MemberInfo> GetSerializableMembers(Type objectType) {
    return base.GetSerializableMembers(objectType).Where(Keep).ToList();
}
Defensive patterns

Strategy: validation

Validate before calling

// If you ship a custom resolver, assert in tests that GetSerializableMembers never returns null.
var resolver = new MyCustomResolver();
foreach (var t in typesUnderTest)
{
    var members = resolver.GetSerializableMembers(t);
    if (members == null)
        throw new InvalidOperationException($"GetSerializableMembers returned null for {t}.");
}

Type guard

// n/a: this is a contract for an override, not a runtime type test

Try / catch

try { JsonConvert.SerializeObject(value, settings); }
catch (JsonSerializationException ex) when (ex.Message == "Null collection of serializable members returned.")
{
    // fix the custom resolver override to return an empty list instead of null
}

Prevention

When it happens

Trigger: A custom DefaultContractResolver (or IContractResolver) override of GetSerializableMembers that returns null instead of a (possibly empty) IList<MemberInfo>.

Common situations: Writing a custom resolver and short-circuiting with 'return null;' when no members match a filter.

Related errors


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