{"record":{"id":"a50287a9faf67046","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-begin-observable-async","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'begin')","messagePattern":"Value cannot be null\\. \\(Parameter 'begin'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs","lineNumber":31,"sourceCode":"        #region FromAsyncPattern\n\n        #region Func\n\n        /// <summary>\n        /// Converts a Begin/End invoke function pair into an asynchronous function.\n        /// </summary>\n        /// <typeparam name=\"TResult\">The type of the result returned by the end delegate.</typeparam>\n        /// <param name=\"begin\">The delegate that begins the asynchronous operation.</param>\n        /// <param name=\"end\">The delegate that ends the asynchronous operation.</param>\n        /// <returns>Function that can be used to start the asynchronous operation and retrieve the result as an observable sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"begin\"/> or <paramref name=\"end\"/> is null.</exception>\n        /// <remarks>Each invocation of the resulting function will cause the asynchronous operation to be started. Subscription to the resulting sequence has no observable side-effect, and each subscription will produce the asynchronous operation's result.</remarks>\n        [Obsolete(Constants_Linq.UseTaskFromAsyncPattern)]\n        public static Func<IObservable<TResult>> FromAsyncPattern<TResult>(Func<AsyncCallback, object?, IAsyncResult> begin, Func<IAsyncResult, TResult> end)\n        {\n            if (begin == null)\n            {\n                throw new ArgumentNullException(nameof(begin));\n            }\n\n            if (end == null)\n            {\n                throw new ArgumentNullException(nameof(end));\n            }\n\n            return s_impl.FromAsyncPattern(begin, end);\n        }\n\n        /// <summary>\n        /// Converts a Begin/End invoke function pair into an asynchronous function.\n        /// </summary>\n        /// <typeparam name=\"TArg1\">The type of the first argument passed to the begin delegate.</typeparam>\n        /// <typeparam name=\"TResult\">The type of the result returned by the end delegate.</typeparam>\n        /// <param name=\"begin\">The delegate that begins the asynchronous operation.</param>\n        /// <param name=\"end\">The delegate that ends the asynchronous operation.</param>\n        /// <returns>Function that can be used to start the asynchronous operation and retrieve the result as an observable sequence.</returns>","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs#L13-L49","documentation":"Observable.FromAsyncPattern<TResult> (the legacy Begin/End APM wrapper, marked obsolete in favor of Task-based APIs) eagerly validates the begin delegate and throws ArgumentNullException when it is null. The check runs when the wrapper function is created, before it is invoked or subscribed to.","triggerScenarios":"Calling Observable.FromAsyncPattern(begin, end) with a null begin delegate — e.g. a BeginXxx method reference obtained via reflection that failed, or an uninitialized delegate variable, while end may also be null (its check follows).","commonSituations":"Migrating legacy APM code where Begin/End pairs are wired dynamically; reflection-based method lookup returning null when the method name/signature changed across framework versions; obsolete-API usage that was only partially ported.","solutions":["Pass valid begin/end delegates, e.g. Observable.FromAsyncPattern(stream.BeginRead, stream.EndRead).","Prefer the modern alternative: use Observable.FromTask/ToObservable with Task-based APIs (TaskFactory.FromAsync or native *Async methods) instead of the obsolete FromAsyncPattern.","If delegates are resolved dynamically, null-check the MethodInfo/delegate result before calling the factory."],"exampleFix":"// before\nvar read = Observable.FromAsyncPattern<byte[]>(beginMethod, endMethod); // beginMethod == null\n// after\nvar read = Observable.FromAsyncPattern<byte[]>(stream.BeginRead, stream.EndRead);\n// or prefer task-based:\nvar read = () => Observable.FromTask(stream.ReadAsync(buffer, offset, count));","handlingStrategy":"validation","validationCode":"if (begin == null || end == null)\n    throw new ArgumentNullException(nameof(begin), \"FromAsyncPattern requires non-null begin/end delegates\");\nvar read = begin != null && end != null ? Observable.FromAsyncPattern(begin, end) : null;","typeGuard":"bool HasApmPair(Func<AsyncCallback, object?, IAsyncResult>? begin, Func<IAsyncResult, TResult>? end)\n    => begin != null && end != null;","tryCatchPattern":"try { var op = Observable.FromAsyncPattern(begin, end); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"begin\") { /* repair Begin-method reference */ }","preventionTips":["Avoid the obsolete APM wrapper; prefer Task-based APIs with Observable.FromTask.","If resolving Begin/End methods via reflection, assert both delegates before wiring.","Use method groups (stream.BeginRead, stream.EndRead) so the compiler verifies the pair."],"tags":["rx","async","apm","argument-null","obsolete"],"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"}