{"record":{"id":"884d95ff791660c8","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-end-observable-async","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'end')","messagePattern":"Value cannot be null\\. \\(Parameter 'end'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs","lineNumber":36,"sourceCode":"        /// 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>\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<TArg1, IObservable<TResult>> FromAsyncPattern<TArg1, TResult>(Func<TArg1, AsyncCallback, object?, IAsyncResult> begin, Func<IAsyncResult, TResult> end)\n        {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs#L18-L54","documentation":"Observable.FromAsyncPattern validates its begin/end delegate arguments up front and throws ArgumentNullException('end') when the end (IAsyncResult result selector) delegate is null. The APM Begin/End pattern requires both delegates to wrap an async operation into an IObservable, so a null end delegate cannot produce a valid sequence. The library throws eagerly at wrapper creation time rather than at subscription time.","triggerScenarios":"Calling the parameterless Observable.FromAsyncPattern(begin, end) overload with a non-null begin delegate but a null end delegate, e.g. FromAsyncPattern(begun, null) or passing a variable that was never assigned.","commonSituations":"Converting legacy Stream/WebRequest BeginXxx/EndXxx pairs to Rx; the End delegate is looked up via reflection or config and the lookup returns null; refactoring removed the end method but the call site still compiles because the parameter accepts any Func.","solutions":["Ensure a non-null end delegate Func<IAsyncResult, TResult> is passed as the second argument","Check that any reflection/config lookup producing the end delegate succeeded before calling FromAsyncPattern","Prefer the modern Task-based FromAsync pattern (Observable.FromAsync of a Func<Task<T>>) which avoids Begin/End pairs entirely"],"exampleFix":"// before\nvar end = (Func<IAsyncResult, string>)null;\nvar f = Observable.FromAsyncPattern<string>(begin, end);\n// after\nvar end = iar => ((FileStream)iar.AsyncState).EndRead(iar) is var n ? Encoding.UTF8.GetString(n == 0 ? Array.Empty<byte>() : buffer, 0, n) : null;\nvar f = Observable.FromAsyncPattern<string>(begin, end);","handlingStrategy":"validation","validationCode":"if (end == null) throw new InvalidOperationException(\"FromAsyncPattern requires a non-null end delegate\");\nvar f = Observable.FromAsyncPattern<TResult>(begin, end);","typeGuard":"static bool HasBeginEnd<TArg,TResult>(Func<TArg, AsyncCallback, object?, IAsyncResult> begin, Func<IAsyncResult, TResult> end) => begin != null && end != null;","tryCatchPattern":"try\n{\n    var f = Observable.FromAsyncPattern<TResult>(begin, end);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"end\")\n{\n    // supply or repair the end delegate\n}","preventionTips":["Always pass the EndXxx method group together with its BeginXxx counterpart","Null-check delegates resolved via reflection or configuration before wrapping","Prefer Observable.FromAsync with Task-based APIs over obsolete FromAsyncPattern"],"tags":["csharp","null-argument","rx","async"],"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"}