JamesNK/Newtonsoft.Json · error · InvalidOperationException

Cannot get SerializationBinder because an ISerializationBind

Error message

Cannot get SerializationBinder because an ISerializationBinder was previously set.

What it means

Thrown by the obsolete JsonSerializerSettings.Binder getter when the underlying SerializationBinder (ISerializationBinder) was set to a type that is neither a SerializationBinderAdapter nor directly a legacy SerializationBinder. The new ISerializationBinder contract is broader than the obsolete abstract class, so the getter cannot represent it and throws InvalidOperationException. Migrate reads to the SerializationBinder property.

Source

Thrown at Src/Newtonsoft.Json/JsonSerializerSettings.cs:290

        /// Gets or sets the <see cref="SerializationBinder"/> used by the serializer when resolving type names.
        /// </summary>
        /// <value>The binder.</value>
        [Obsolete("Binder is obsolete. Use SerializationBinder instead.")]
        public SerializationBinder? Binder
        {
            get
            {
                if (SerializationBinder == null)
                {
                    return null;
                }

                if (SerializationBinder is SerializationBinderAdapter adapter)
                {
                    return adapter.SerializationBinder;
                }

                throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set.");
            }
            set => SerializationBinder = value == null ? null : new SerializationBinderAdapter(value);
        }

        /// <summary>
        /// Gets or sets the <see cref="ISerializationBinder"/> used by the serializer when resolving type names.
        /// </summary>
        /// <value>The binder.</value>
        public ISerializationBinder? SerializationBinder { get; set; }

        /// <summary>
        /// Gets or sets the error handler called during serialization and deserialization.
        /// </summary>
        /// <value>The error handler called during serialization and deserialization.</value>
        public EventHandler<ErrorEventArgs>? Error { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="StreamingContext"/> used by the serializer when invoking serialization callback methods.

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Read/write through the SerializationBinder (ISerializationBinder) property exclusively.
  2. If the legacy SerializationBinder object is genuinely needed, assign it via the Binder setter so it is stored as an adapter the getter understands.
  3. Update all consumers off the obsolete property and clear the Obsolete warning.

Example fix

// before
SerializationBinder b = settings.Binder; // throws

// after
ISerializationBinder b = settings.SerializationBinder;
Defensive patterns

Strategy: validation

Validate before calling

#pragma warning disable CS0618
SerializationBinder legacy = null;
try { legacy = settings.Binder; }
catch (InvalidOperationException) { /* read settings.SerializationBinder instead */ }
#pragma warning restore CS0618

Type guard

static bool CanReadLegacyBinder(JsonSerializerSettings s)
{
    var b = s.SerializationBinder;
    return b is null or SerializationBinderAdapter or SerializationBinder;
}

Prevention

When it happens

Trigger: Reading settings.Binder (obsolete) after settings.SerializationBinder was assigned a custom ISerializationBinder not derived from legacy SerializationBinder.

Common situations: Libraries/serializers still consuming the obsolete Binder property; migration from legacy API; DI-registered ISerializationBinder assigned then legacy code reads Binder.

Related errors


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