{"record":{"id":"54bd4496cbed9a15","repo":"dotnet/reactive","slug":"addhandler-fromeventpattern","errorCode":null,"errorMessage":"addHandler","messagePattern":"addHandler","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs","lineNumber":21,"sourceCode":"// See the LICENSE file in the project root for more information. \n\nusing System.Globalization;\nusing System.Reactive.Concurrency;\nusing System.Reactive.Disposables;\nusing System.Reflection;\nusing System.Runtime.ExceptionServices;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<EventPattern<object>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler) => FromEventPattern(addHandler, removeHandler, GetSchedulerForCurrentContext());\n\n        public static IAsyncObservable<EventPattern<object>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler, IAsyncScheduler scheduler)\n        {\n            if (addHandler == null)\n                throw new ArgumentNullException(nameof(addHandler));\n            if (removeHandler == null)\n                throw new ArgumentNullException(nameof(removeHandler));\n            if (scheduler == null)\n                throw new ArgumentNullException(nameof(scheduler));\n\n            return FromEvent<EventHandler, object, EventArgs>(\n                action => new EventHandler((o, e) => action(o, e)),\n                addHandler,\n                removeHandler,\n                scheduler).Select(t => new EventPattern<object>(t.arg1, t.arg2));\n        }\n\n        public static IAsyncObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler) => FromEventPattern<TDelegate, TEventArgs>(addHandler, removeHandler, GetSchedulerForCurrentContext());\n\n        public static IAsyncObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IAsyncScheduler scheduler)\n        {\n            if (addHandler == null)\n                throw new ArgumentNullException(nameof(addHandler));","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs#L3-L39","documentation":"FromEventPattern(addHandler, removeHandler, scheduler) validates arguments in order; this error means addHandler (an Action<EventHandler>) was null. Since FromEventPattern forwards to FromEvent<EventHandler, object, EventArgs>, the null addHandler makes the event subscription impossible and the guard throws ArgumentNullException with ParamName \"addHandler\".","triggerScenarios":"Calling FromEventPattern(null, removeHandler) or FromEventPattern(null, removeHandler, scheduler), e.g. FromEventPattern(null, h => src.Event -= h).","commonSituations":"Reflection overloads (FromEventPattern(name)) resolved elsewhere but here wiring delegates directly from a lookup table where the add entry is missing; swapping add/remove by mistake; event source obtained from an uninitialized control so the accessor lambda was never built.","solutions":["Pass the event's add accessor: h => src.Clicked += h.","Use the string/EventInfo-based FromEventPattern overloads when wiring via reflection, which resolve accessors for you.","Verify add/remove arguments are in the right order and the source object is initialized."],"exampleFix":"// before\nvar sub = AsyncRx.Observable.FromEventPattern(null, h => src.Clicked -= h);\n// after\nvar sub = AsyncRx.Observable.FromEventPattern(h => src.Clicked += h, h => src.Clicked -= h);","handlingStrategy":"validation","validationCode":"if (addHandler == null || removeHandler == null) throw new ArgumentException(\"Both addHandler and removeHandler are required, e.g. h => src.Clicked += h / h => src.Clicked -= h\");","typeGuard":"bool CanSubscribePattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler) => addHandler != null && removeHandler != null;","tryCatchPattern":"try { var sub = FromEventPattern(add, remove); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"addHandler\") { /* check argument order and source initialization */ }","preventionTips":["FromEventPattern expects EventHandler delegates; pass += accessor first, -= accessor second.","Prefer the string-name FromEventPattern overloads when events are resolved by reflection.","Verify the event source object exists before constructing accessor lambdas."],"tags":["csharp","argument-null","fromeventpattern","event-operators","asyncrx"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}