dotnet/reactive · error · InvalidOperationException

The event arguments parameter of the event is not…

Error message

The event arguments parameter of the event is not assignable to '{0}'.

What it means

GetEventMethods checks that the delegate's second parameter (the event arguments) is assignable to TEventArgs. This InvalidOperationException is thrown when the delegate's event-args parameter type does not derive from / match the TEventArgs generic argument, so the adapter cannot convert the event payload for the observable.

Solutions

  1. Set TEventArgs to the exact type (or a base type) of the delegate's second Invoke parameter, e.g. FromEventPattern<object, KeyEventArgs>
  2. Check typeof(D).GetMethod("Invoke").GetParameters()[1].ParameterType and ensure TEventArgs.IsAssignableFrom(that type)
  3. Prefer the EventHandler<TEventArgs>-based overloads which infer TEventArgs correctly

Example fix

// before
AsyncObservable.FromEventPattern<object, EventArgs>(h => keySrc.PreviewKeyDown += h, h => keySrc.PreviewKeyDown -= h); // args are KeyEventArgs
// after
AsyncObservable.FromEventPattern<object, KeyEventArgs>(h => keySrc.PreviewKeyDown += h, h => keySrc.PreviewKeyDown -= h);
Defensive patterns

Strategy: validation

Validate before calling

var p = typeof(MyDelegate).GetMethod("Invoke").GetParameters();
if (!typeof(TEventArgs).IsAssignableFrom(p[1].ParameterType))
    throw new InvalidOperationException($"TEventArgs must accept {p[1].ParameterType}");

Type guard

static bool EventArgsCompatible<TEventArgs>(Type d)
    => typeof(TEventArgs).IsAssignableFrom(d.GetMethod("Invoke")?.GetParameters()[1].ParameterType);

Try / catch

try
{
    var obs = AsyncObservable.FromEventPattern<TSender, TEventArgs>(add, remove);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("arguments parameter"))
{
    // correct TEventArgs to the delegate's actual args type and retry
}

Prevention

When it happens

Trigger: Calling FromEventPattern<TSender, TEventArgs> where TEventArgs is a base class (e.g. EventArgs) but the delegate's second parameter is a derived type the caller failed to specify, or vice versa — a completely unrelated TEventArgs type.

Common situations: Using the non-generic EventArgs as TEventArgs with a delegate carrying specific args; typos in generic arguments; events whose delegate uses a custom args class not related to the one supplied.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/d38205c9878eedc2. Report an issue: GitHub.

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs:319

                var pet = psr[0];
                if (pet.ParameterType != addMethod.ReturnType)
                    throw new InvalidOperationException("An event should either have add and remove methods that return void or an add method that returns a type compatible with the parameter type of the remove method.");
            }

            var delegateType = psa[0].ParameterType;

            var invokeMethod = delegateType.GetMethod("Invoke");

            var parameters = invokeMethod.GetParameters();

            if (parameters.Length != 2)
                throw new InvalidOperationException("The delegate type for an event conforming to the traditional event pattern should take two parameters.");

            if (!typeof(TSender).IsAssignableFrom(parameters[0].ParameterType))
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "The sender parameter of the event is not assignable to '{0}'.", typeof(TSender).FullName));

            if (!typeof(TEventArgs).IsAssignableFrom(parameters[1].ParameterType))
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "The event arguments parameter of the event is not assignable to '{0}'.", typeof(TEventArgs).FullName));

            if (invokeMethod.ReturnType != typeof(void))
                throw new InvalidOperationException("The return type of an event delegate should be void.");

            return (addMethod, removeMethod, delegateType, isWinRT);
        }

        public static EventInfo GetEventEx(this Type type, string name, bool isStatic)
        {
            return type.GetEvent(name, isStatic ? BindingFlags.Public | BindingFlags.Static : BindingFlags.Public | BindingFlags.Instance);
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)