dotnet/reactive · error · InvalidOperationException
Strings_Linq.EVENT_PATTERN_REQUIRES_TWO_PARAMETERS
Error message
Strings_Linq.EVENT_PATTERN_REQUIRES_TWO_PARAMETERS
What it means
The delegate behind the event must follow the .NET event pattern: two parameters (sender, eventArgs). Rx's FromEventPattern projects events into (TSender, TEventArgs) pairs, so a delegate's Invoke method with a parameter count other than 2 cannot be adapted. GetEventMethods throws InvalidOperationException when this invariant fails.
Solutions
- Use a delegate type conforming to the event pattern, e.g. EventHandler<TEventArgs> or a custom delegate with (object sender, TEventArgs e).
- If the event really passes only a payload, use Observable.FromEvent instead of FromEventPattern.
- Check that the event name string passed to FromEventPattern resolves to the intended event.
Example fix
// before public event Action<int> Tick; // after public event EventHandler<int> Tick;
Defensive patterns
Strategy: validation
Validate before calling
var invoke = delegateType.GetMethod("Invoke");
if (invoke == null || invoke.GetParameters().Length != 2)
throw new ArgumentException("Delegate must follow (object sender, TEventArgs e) pattern"); Try / catch
try
{
var src = Observable.FromEventPattern<TSender, TEventArgs>(target, eventName);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("two parameters"))
{
var src2 = Observable.FromEvent<Action<TPayload>, TPayload>(h => h.Invoke, h => target.Event += h, h => target.Event -= h);
} Prevention
- Define events with EventHandler<TEventArgs> or matching (sender, args) delegates.
- Use Observable.FromEvent (not FromEventPattern) for non-pattern delegates.
- Check the delegate signature before choosing the operator.
When it happens
Trigger: Calling FromEventPattern<TSender, TEventArgs> with an event whose delegate type (or the delegate of the add method's parameter) has an Invoke method taking 0, 1, or 3+ parameters.
Common situations: Using delegates like Action or custom single-arg delegates (e.g. Action<string> callbacks) as 'events'; passing the wrong event name so reflection resolves an unrelated delegate; migrating code to FromEvent (delegate-based) when FromEventPattern (sender/args) was assumed.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- The delegate type for an event conforming to the…
- The return type of an event delegate should be void.
- Strings_Linq.EVENT_REMOVE_METHOD_SHOULD_TAKE_ONE_PARAMETER
- Strings_Linq.EVENT_WINRT_REMOVE_METHOD_SHOULD_TAKE_ERT
- Strings_Linq.EVENT_MUST_RETURN_VOID
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/36f8c9cc66ffcf89.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Internal/ReflectionUtils.cs:77
{
isWinRT = true;
var pet = psr[0];
if (IsWinRTEventRegistrationTokenType(pet.ParameterType))
{
throw new InvalidOperationException(Strings_Linq.EVENT_WINRT_REMOVE_METHOD_SHOULD_TAKE_ERT);
}
}
delegateType = psa[0].ParameterType;
var invokeMethod = delegateType.GetMethod("Invoke")!; // NB: Delegates always have an Invoke method.
var parameters = invokeMethod.GetParameters();
if (parameters.Length != 2)
{
throw new InvalidOperationException(Strings_Linq.EVENT_PATTERN_REQUIRES_TWO_PARAMETERS);
}
if (!typeof(TSender).IsAssignableFrom(parameters[0].ParameterType))
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_SENDER_NOT_ASSIGNABLE, typeof(TSender).FullName));
}
if (!typeof(TEventArgs).IsAssignableFrom(parameters[1].ParameterType))
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_ARGS_NOT_ASSIGNABLE, typeof(TEventArgs).FullName));
}
if (invokeMethod.ReturnType != typeof(void))
{
throw new InvalidOperationException(Strings_Linq.EVENT_MUST_RETURN_VOID);
}
}
View on GitHub (pinned to 94b5d5ab91)