dotnet/reactive · error · InvalidOperationException
Strings_Linq.EVENT_WINRT_REMOVE_METHOD_SHOULD_TAKE_ERT
Error message
Strings_Linq.EVENT_WINRT_REMOVE_METHOD_SHOULD_TAKE_ERT
What it means
For WinRT events, the remove accessor must take an EventRegistrationToken, not the delegate type. GetEventMethods detects a WinRT event (add method returns an EventRegistrationToken) and then validates the remove parameter; if the remove parameter is not an EventRegistrationToken the pattern is inconsistent and Rx throws InvalidOperationException.
Solutions
- Make the remove accessor accept a single Windows.Foundation.EventRegistrationToken parameter to match the add accessor's return type.
- Regenerate the WinRT interop types with cswinrt / the current Windows SDK metadata so add/remove conventions match.
- Wrap the event manually with Observable.Create if you cannot fix the interop type.
Example fix
// before
public void remove_E(EventHandler h) { ... }
// after
public void remove_E(EventRegistrationToken t) { ... } Defensive patterns
Strategy: validation
Validate before calling
var remove = type.GetMethod("remove_" + name);
var p = remove?.GetParameters();
if (p == null || p.Length != 1 || p[0].ParameterType.Name != "EventRegistrationToken")
throw new ArgumentException("WinRT event remove accessor must take EventRegistrationToken"); Try / catch
try { Observable.FromEventPattern(target, eventName); }
catch (InvalidOperationException ex) when (ex.Message.Contains("ERT") || ex.Message.Contains("EventRegistrationToken"))
{
// use platform-specific WinRT event extension or manual wiring
} Prevention
- Regenerate WinRT interop assemblies with current cswinrt tooling.
- Never hand-edit projected WinRT event accessors.
- Target .NET versions with proper WinRT projection support.
When it happens
Trigger: Calling FromEventPattern on a WinRT event whose remove_X accessor takes a delegate instead of a Windows.Foundation.EventRegistrationToken while the add_X accessor returns a token.
Common situations: Mixed/mismatched WinRT projections; manually authored interop stubs where add and remove use different conventions; consuming WinRT metadata converted with incorrect tooling on .NET (pre-.NET Core 3 WinRT support changes).
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
- An event should either have add and remove methods that…
- 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_PATTERN_REQUIRES_TWO_PARAMETERS
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/58bd84213650c172.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Internal/ReflectionUtils.cs:65
throw new InvalidOperationException(Strings_Linq.EVENT_ADD_METHOD_SHOULD_TAKE_ONE_PARAMETER);
}
var psr = removeMethod.GetParameters();
if (psr.Length != 1)
{
throw new InvalidOperationException(Strings_Linq.EVENT_REMOVE_METHOD_SHOULD_TAKE_ONE_PARAMETER);
}
isWinRT = false;
if (IsWinRTEventRegistrationTokenType(addMethod.ReturnType))
{
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));
}View on GitHub (pinned to 94b5d5ab91)