dotnet/reactive · error · InvalidOperationException
Missing remove method on event.
Error message
Missing remove method on event.
What it means
The located EventInfo has no accessible remove accessor (GetRemoveMethod() returned null). Even if subscribing (add) is possible, the library cannot guarantee unsubscription and rejects the event with InvalidOperationException.
Solutions
- Declare the event with both add and remove accessors if you control the type
- Use the FromEvent overload with explicit add/remove delegate pairs if you must work with an add-only event and can manage lifetime yourself
- Check assembly trimming settings and preserve the event accessors (e.g. [DynamicDependency] / linker XML)
Example fix
// before
public event EventHandler Tick { add { _tick += value; } } // no remove
// after
public event EventHandler Tick { add { _tick += value; } remove { _tick -= value; } } Defensive patterns
Strategy: validation
Validate before calling
var ev = type.GetEvent(eventName);
if (ev?.GetRemoveMethod() is null) throw new NotSupportedException($"Event '{eventName}' has no accessible remove accessor."); Type guard
static bool HasRemoveAccessor(Type t, string name) => t.GetEvent(name)?.GetRemoveMethod() is not null;
Try / catch
try { var obs = AsyncObservable.FromEventPattern<TSender, TEventArgs>(target, eventName); }
catch (InvalidOperationException ex) { log.LogError(ex, "Event {Event} lacks a remove accessor; cannot guarantee unsubscribe", eventName); throw; } Prevention
- Always declare both add and remove accessors on custom events
- Preserve accessors in trimmed builds ([DynamicDependency] or linker XML)
- Test subscribe/unsubscribe lifecycle for custom events
When it happens
Trigger: Events with an add accessor but a missing/non-public remove accessor, e.g. hand-written event field declarations like 'event EventHandler E { add {} }' or trimmed assemblies where the remove method was stripped.
Common situations: Custom event implementations that only support add (fire-and-forget hook points), IL trimming/linker stripping unused accessors, obfuscation tools renaming/removing methods.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Missing add method on event.
- Could not find static event
- Could not find instance event
- The add method of an event should take one parameter.
- The remove method of an event should take one parameter.
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/c5df404c48803ccf.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs:285
{
e = targetType.GetEventEx(eventName, isStatic: true);
if (e == null)
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Could not find static event '{0}' on type '{1}'.", eventName, targetType.FullName));
}
else
{
e = targetType.GetEventEx(eventName, isStatic: false);
if (e == null)
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Could not find instance event '{0}' on type '{1}'.", eventName, targetType.FullName));
}
var addMethod = e.GetAddMethod();
var removeMethod = e.GetRemoveMethod();
if (addMethod == null)
throw new InvalidOperationException("Missing add method on event.");
if (removeMethod == null)
throw new InvalidOperationException("Missing remove method on event.");
var psa = addMethod.GetParameters();
if (psa.Length != 1)
throw new InvalidOperationException("The add method of an event should take one parameter.");
var psr = removeMethod.GetParameters();
if (psr.Length != 1)
throw new InvalidOperationException("The remove method of an event should take one parameter.");
var isWinRT = false;
if (addMethod.ReturnType != typeof(void))
{
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.");View on GitHub (pinned to 94b5d5ab91)