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 JsonSerializer.Binder getter (legacy SerializationBinder API) when the field holds an ISerializationBinder that is neither a SerializationBinder subclass nor a SerializationBinderAdapter. Because the new ISerializationBinder abstraction is broader than the legacy abstract SerializationBinder class, the getter cannot losslessly return it, so it throws InvalidOperationException. The fix is to use the SerializationBinder (ISerializationBinder) property instead of the obsolete Binder.

Source

Thrown at Src/Newtonsoft.Json/JsonSerializer.cs:123

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

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

                throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set.");
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value), "Serialization binder cannot be null.");
                }

                _serializationBinder = value as ISerializationBinder ?? new SerializationBinderAdapter(value);
            }
        }

        /// <summary>
        /// Gets or sets the <see cref="ISerializationBinder"/> used by the serializer when resolving type names.
        /// </summary>
        public virtual ISerializationBinder SerializationBinder
        {
            get => _serializationBinder;

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Switch all reads/writes to the SerializationBinder property (ISerializationBinder) and stop using the obsolete Binder.
  2. If a legacy SerializationBinder is required, assign via the Binder setter so it is wrapped in a SerializationBinderAdapter the getter can unwrap.
  3. Suppress the Obsolete warning only after migrating callers off Binder.

Example fix

// before
var b = serializer.Binder; // throws if ISerializationBinder set

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

Strategy: validation

Validate before calling

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

Type guard

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

Prevention

When it happens

Trigger: Reading serializer.Binder after serializer.SerializationBinder was set to a custom ISerializationBinder implementation that does not derive from the legacy SerializationBinder class.

Common situations: Interoperating with code/libraries that still use the obsolete Binder property; migrating from the legacy API; a DI-registered ISerializationBinder being assigned then legacy code reading Binder.

Related errors


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