{"record":{"id":"7c960f88869ad49a","repo":"dotnet/reactive","slug":"strings-linq-event-missing-add-method","errorCode":null,"errorMessage":"Strings_Linq.EVENT_MISSING_ADD_METHOD","messagePattern":"Strings_Linq\\.EVENT_MISSING_ADD_METHOD","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Internal/ReflectionUtils.cs","lineNumber":41,"sourceCode":"#if HAS_TRIMMABILITY_ATTRIBUTES\n    [RequiresUnreferencedCode(Constants_Core.EventReflectionTrimIncompatibilityMessage)]\n#endif\n        public static void GetEventMethods<TSender, TEventArgs>(Type targetType, object? target, string eventName, out MethodInfo addMethod, out MethodInfo removeMethod, out Type delegateType, out bool isWinRT)\n        {\n            EventInfo? e;\n\n            if (target == null)\n            {\n                e = targetType.GetEvent(eventName, BindingFlags.Public | BindingFlags.Static)\n                    ?? throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_STATIC_EVENT, eventName, targetType.FullName));\n            }\n            else\n            {\n                e = targetType.GetEvent(eventName, BindingFlags.Public | BindingFlags.Instance)\n                    ?? throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_INSTANCE_EVENT, eventName, targetType.FullName));\n            }\n\n            addMethod = e.GetAddMethod() ?? throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_ADD_METHOD);\n            removeMethod = e.GetRemoveMethod() ?? throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_REMOVE_METHOD);\n\n            var psa = addMethod.GetParameters();\n            if (psa.Length != 1)\n            {\n                throw new InvalidOperationException(Strings_Linq.EVENT_ADD_METHOD_SHOULD_TAKE_ONE_PARAMETER);\n            }\n\n            var psr = removeMethod.GetParameters();\n            if (psr.Length != 1)\n            {\n                throw new InvalidOperationException(Strings_Linq.EVENT_REMOVE_METHOD_SHOULD_TAKE_ONE_PARAMETER);\n            }\n\n            isWinRT = false;\n\n            if (IsWinRTEventRegistrationTokenType(addMethod.ReturnType))\n            {","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Internal/ReflectionUtils.cs#L23-L59","documentation":"After locating the EventInfo, GetEventMethods fetches its add accessor; if the event has no public add method (e.g. custom event accessors where add is private or the event is abstract-in-metadata), it throws InvalidOperationException 'Event missing add method'. FromEventPattern needs add/remove to subscribe.","triggerScenarios":"FromEventPattern against an event whose add accessor is non-public or missing — custom add/remove accessors with private add, events defined in non-public interfaces, or platform events with restricted accessors.","commonSituations":"Events with custom accessors (add private, remove public); COM/WinRT interop events; events bound in Reflection-only contexts where accessors aren't resolvable.","solutions":["Make the event's add accessor public, or subscribe through the public surface instead.","Use the delegate-based FromEventPattern overloads (explicit addHandler/removeHandler lambdas) that call the accessors you specify.","If subscribing from another assembly, ensure the event's accessors are at least InternalsVisibleTo-visible and adjust to public."],"exampleFix":"// before\nprivate event EventHandler E { add { } remove { } }\n// after\npublic event EventHandler E { add { } remove { } }","handlingStrategy":"validation","validationCode":"var evt = targetType.GetEvent(eventName, BindingFlags.Public | BindingFlags.Instance);\nif (evt?.GetAddMethod() == null) throw new NotSupportedException($\"Event '{eventName}' has no public add accessor\");","typeGuard":"static bool HasPublicAdd(Type t, string name) => t.GetEvent(name)?.GetAddMethod() != null;","tryCatchPattern":"try { Observable.FromEventPattern(target, eventName, targetType); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"add method\")) { /* use explicit add/remove overloads */ }","preventionTips":["Declare events with standard public accessors.","Check EventInfo.GetAddMethod() != null before reflection subscription.","Use FromEventPattern(handler => target.Ev += handler, handler => target.Ev -= handler) to bypass accessor discovery."],"tags":["reflection","event","accessor"],"backgroundTag":"missing-dependency","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}