dotnet/reactive · error · InvalidOperationException
The sender parameter of the event is not assignable to
Error message
The sender parameter of the event is not assignable to '{0}'. What it means
After checking parameter count, GetEventMethods verifies that the delegate's first parameter type is assignable to TSender (typically object). This InvalidOperationException fires when the sender slot of the delegate has a type that TSender cannot accept, so the FromEventPattern adapter cannot safely deliver the sender argument as TSender.
Solutions
- Make TSender assignable-from the delegate's first parameter, typically use object for TSender
- Match the delegate's sender parameter type exactly, e.g. FromEventPattern<MyControl, MyEventArgs> for a delegate taking (MyControl sender, MyEventArgs e)
- Inspect the delegate: typeof(D).GetMethod("Invoke").GetParameters()[0].ParameterType and ensure TSender.IsAssignableFrom(that type)
Example fix
// before AsyncObservable.FromEventPattern<object, MyEventArgs>(...) // delegate sender is MyControl, object is not assignable FROM MyControl? -> use actual types // after AsyncObservable.FromEventPattern<MyControl, MyEventArgs>(...)
Defensive patterns
Strategy: validation
Validate before calling
var p = typeof(MyDelegate).GetMethod("Invoke").GetParameters();
if (!typeof(TSender).IsAssignableFrom(p[0].ParameterType))
throw new InvalidOperationException($"TSender must accept {p[0].ParameterType}"); Type guard
static bool SenderCompatible<TSender>(Type d)
=> typeof(TSender).IsAssignableFrom(d.GetMethod("Invoke")?.GetParameters()[0].ParameterType); Try / catch
try
{
var obs = AsyncObservable.FromEventPattern<TSender, TEventArgs>(add, remove);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("sender parameter"))
{
// retry with TSender = the delegate's actual sender parameter type
} Prevention
- Use object as TSender unless you deliberately need a narrower type
- Match TSender to the delegate's first Invoke parameter exactly
- Avoid hand-copying generic arguments between different events
When it happens
Trigger: Calling FromEventPattern<TSender, TEventArgs> with a delegate whose first Invoke parameter is a concrete type (e.g. MyControl) while TSender is a base type like object, or TSender set to a type unrelated to the delegate's actual sender parameter.
Common situations: Specifying an incorrect TSender generic argument (e.g. typeof(object) expected but the delegate narrows the sender); using custom delegates with strongly-typed senders; copy-pasting generic arguments from another event.
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
- The event arguments parameter of the event is not…
- An event should either have add and remove methods that…
- Strings_Linq.EVENT_ARGS_NOT_ASSIGNABLE
- Strings_Linq.EVENT_SENDER_NOT_ASSIGNABLE
- Could not find instance event
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/1cb3f5c7a19084e9.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs:316
{
isWinRT = true;
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)