JamesNK/Newtonsoft.Json · error · NotSupportedException

Newtonsoft.Json support for dynamic is not compatible with t

Error message

Newtonsoft.Json support for dynamic is not compatible with trimming and has been disabled. Newtonsoft.Json.Linq.JToken.DynamicIsSupported is set to false.

What it means

Same dynamic-trimming guard as the JToken version, raised from JValue.GetMetaObject (the overridden IDynamicMetaObjectProvider hook). When the runtime attempts dynamic dispatch (dynamic keyword / ConvertBinder) against a JValue and the feature switch Newtonsoft.Json.Linq.JToken.DynamicIsSupported is false, Newtonsoft throws NotSupportedException. JValue has its own JValueDynamicProxy that relies on reflection/MakeDynamic, which trimming removes, so the guard protects AOT/trimmed apps.

Source

Thrown at Src/Newtonsoft.Json/Linq/JValue.cs:980

            {
                return _value.ToString()!;
            }
        }

#if HAVE_DYNAMIC
        /// <summary>
        /// Returns the <see cref="DynamicMetaObject"/> responsible for binding operations performed on this object.
        /// </summary>
        /// <param name="parameter">The expression tree representation of the runtime value.</param>
        /// <returns>
        /// The <see cref="DynamicMetaObject"/> to bind this object.
        /// </returns>
        protected override DynamicMetaObject GetMetaObject(Expression parameter)
        {
#if HAVE_APPCONTEXT
            if (!DynamicIsSupported)
            {
                throw new NotSupportedException(DynamicNotSupportedMessage);
            }
#endif
#pragma warning disable IL2026, IL3050
            return new DynamicProxyMetaObject<JValue>(parameter, this, new JValueDynamicProxy());
#pragma warning restore IL2026, IL3050
        }

        [RequiresUnreferencedCode(MiscellaneousUtils.TrimWarning)]
        [RequiresDynamicCode(MiscellaneousUtils.AotWarning)]
        private class JValueDynamicProxy : DynamicProxy<JValue>
        {
            public override bool TryConvert(JValue instance, ConvertBinder binder, [NotNullWhen(true)]out object? result)
            {
                if (binder.Type == typeof(JValue) || binder.Type == typeof(JToken))
                {
                    result = instance;
                    return true;
                }

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Use explicit casts/indexers instead of dynamic: (int)jvalue or jvalue.Value<int>().
  2. Deserialize to a strongly typed POCO with ToObject<T>().
  3. If dynamic is required on a full-framework/non-trimmed build, set Newtonsoft.Json.Linq.JToken.DynamicIsSupported=true and disable trimming.

Example fix

// before
dynamic dyn = jvalue;
int n = dyn;

// after
int n = jvalue.Value<int>();
Defensive patterns

Strategy: validation

Validate before calling

// Avoid dynamic on JValue in trimmed builds; cast explicitly
var n = jvalue.Value<int>();

Type guard

static bool IsDynamicSupported => AppContext.TryGetSwitch("Newtonsoft.Json.Linq.JToken.DynamicIsSupported", out bool s) ? s : true;

Try / catch

try { dynamic d = jvalue; var x = (int)d; } catch (NotSupportedException) { /* use explicit cast */ }

Prevention

When it happens

Trigger: dynamic dyn = jvalue; var x = dyn.SomeProperty; on a trimmed/AOT-published app, or with the AppContext switch Newtonsoft.Json.Linq.JToken.DynamicIsSupported=false. The JValue-specific proxy (TryConvert/TryGetMember) is what triggers GetMetaObject.

Common situations: Publishing with PublishTrimmed/PublishAot; Blazor WASM/MAUI trimmed apps; flipping the switch off after trim warnings; dynamic conversions of JValue to other types.

Related errors


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