JamesNK/Newtonsoft.Json · error · InvalidOperationException

Could not resolve type '{0}'. You may need to add a referenc

Error message

Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.

What it means

BinderWrapper.Init (DynamicUtils.cs:66-84) resolves the Microsoft.CSharp.RuntimeBinder types by reflection (Type.GetType of the fully-qualified BinderTypeName) to support deserializing into `dynamic`. If Microsoft.CSharp.dll is not loaded/referenced, Type.GetType returns null and it throws InvalidOperationException at DynamicUtils.cs:73, advising to add a reference to Microsoft.CSharp.dll.

Source

Thrown at Src/Newtonsoft.Json/Utilities/DynamicUtils.cs:73

            private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, " + CSharpAssemblyName;
            private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, " + CSharpAssemblyName;

            private static object? _getCSharpArgumentInfoArray;
            private static object? _setCSharpArgumentInfoArray;
            private static MethodCall<object?, object?>? _getMemberCall;
            private static MethodCall<object?, object?>? _setMemberCall;
            private static bool _init;

            [RequiresUnreferencedCode(MiscellaneousUtils.TrimWarning)]
            [RequiresDynamicCode(MiscellaneousUtils.AotWarning)]
            private static void Init()
            {
                if (!_init)
                {
                    Type? binderType = Type.GetType(BinderTypeName, false);
                    if (binderType == null)
                    {
                        throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, BinderTypeName));
                    }

                    // None
                    _getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0);
                    // None, Constant | UseCompileTimeType
                    _setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3);
                    CreateMemberCalls();

                    _init = true;
                }
            }

            [RequiresDynamicCode(MiscellaneousUtils.AotWarning)]
            private static object CreateSharpArgumentInfoArray(params int[] values)
            {
                Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName, true)!;
                Type csharpArgumentInfoFlags = Type.GetType(CSharpArgumentInfoFlagsTypeName, true)!;

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Add the Microsoft.CSharp NuGet package (or the assembly reference) to the project.
  2. Avoid deserializing to dynamic; deserialize to a concrete type or to JObject/JToken instead.
  3. If trimming, ensure Microsoft.CSharp is not trimmed (add a trim root / TrimmerRootDescriptor).
  4. On frameworks with HAVE_REFLECTION_BINDER defined, ensure the Binder type is reachable.

Example fix

// before
dynamic d = JsonConvert.DeserializeObject(json); // throws if Microsoft.CSharp missing
// after: add the Microsoft.CSharp package, or
JObject d = JsonConvert.DeserializeObject<JObject>(json);
Defensive patterns

Strategy: validation

Validate before calling

// Detect the missing binder before deserializing to dynamic.
static bool DynamicBinderAvailable() {
    try { return System.AppDomain.CurrentDomain.GetAssemblies().Any(a => a.GetName().Name == "Microsoft.CSharp"); }
    catch { return false; }
}

Type guard

static bool SupportsDynamic() => Type.GetType("Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp") != null;

Try / catch

try { dynamic d = JsonConvert.DeserializeObject(json); } catch (InvalidOperationException ex) when (ex.Message.Contains("Microsoft.CSharp.dll")) { var d = JsonConvert.DeserializeObject<JObject>(json); }

Prevention

When it happens

Trigger: Deserializing JSON into `dynamic`/ExpandoObject (or otherwise exercising the dynamic binder path) on a runtime/framework where the Microsoft.CSharp assembly is absent — only reached when HAVE_REFLECTION_BINDER is not defined.

Common situations: .NET Core / .NET 5+ projects without the Microsoft.CSharp NuGet package; trimmed/AOT apps where the binder was removed; deserializing to dynamic in environments that ship a minimal BCL.

Related errors


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