{"record":{"id":"c3e7061d868d1778","repo":"dotnet/reactive","slug":"onerror-observable-extensions","errorCode":null,"errorMessage":"onError","messagePattern":"onError","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Observable.Extensions.cs","lineNumber":89,"sourceCode":"        /// <param name=\"onNext\">Action to invoke for each element in the observable sequence.</param>\n        /// <param name=\"onError\">Action to invoke upon exceptional termination of the observable sequence.</param>\n        /// <returns><see cref=\"IDisposable\"/> object used to unsubscribe from the observable sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"onNext\"/> or <paramref name=\"onError\"/> is <c>null</c>.</exception>\n        public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (onNext == null)\n            {\n                throw new ArgumentNullException(nameof(onNext));\n            }\n\n            if (onError == null)\n            {\n                throw new ArgumentNullException(nameof(onError));\n            }\n\n            //\n            // [OK] Use of unsafe Subscribe: non-pretentious constructor for an observer; this overload is not to be used internally.\n            //\n            return source.Subscribe/*Unsafe*/(new AnonymousObserver<T>(onNext, onError, Stubs.Nop));\n        }\n\n        /// <summary>\n        /// Subscribes an element handler and a completion handler to an observable sequence.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements in the source sequence.</typeparam>\n        /// <param name=\"source\">Observable sequence to subscribe to.</param>\n        /// <param name=\"onNext\">Action to invoke for each element in the observable sequence.</param>\n        /// <param name=\"onCompleted\">Action to invoke upon graceful termination of the observable sequence.</param>\n        /// <returns><see cref=\"IDisposable\"/> object used to unsubscribe from the observable sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"onNext\"/> or <paramref name=\"onCompleted\"/> is <c>null</c>.</exception>\n        public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action onCompleted)","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Observable.Extensions.cs#L71-L107","documentation":"The Subscribe(source, onNext, onError) overload throws ArgumentNullException with ParamName \"onError\" when the onError Action<Exception> callback is null. Rx validates it eagerly because AnonymousObserver requires a concrete error handler; a null error handler would make notification routing impossible.","triggerScenarios":"Calling source.Subscribe(onNext, null) or passing an error-handler variable that was never assigned or was set to null by configuration.","commonSituations":"Logging hooks configured to null to 'disable' error logging; test scaffolding that only supplies onNext; refactor that moved the error handler but left the call site unchanged.","solutions":["Pass a non-null onError delegate, e.g. ex => throw ex or a logging action.","If you do not want to handle errors, use the onCompleted-only overload (source.Subscribe(onNext, onCompleted)), which supplies Stubs.Throw internally.","Verify the handler field is populated before subscribing."],"exampleFix":"// before\nsource.Subscribe(x => Handle(x), null); // ArgumentNullException: onError\n\n// after\nsource.Subscribe(x => Handle(x), ex => Console.WriteLine(ex));","handlingStrategy":"validation","validationCode":"if (onError is null) onError = ex => Console.Error.WriteLine(ex); // or use Subscribe(onNext, onCompleted) overload","typeGuard":"static bool HasErrorHandler<T>(Action<T> onNext, Action<Exception> onError) => onNext is not null && onError is not null;","tryCatchPattern":"try { disposable = source.Subscribe(onNext, onError); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"onError\") { /* install default logging handler */ }","preventionTips":["Always provide an error handler; unhandled errors in Rx terminate the subscription silently.","Do not 'disable' error handling by setting the delegate to null; use a no-op or logging handler.","Use Subscribe(onNext, onCompleted) when error handling is intentionally omitted."],"tags":["null-argument","rx","subscribe","error-handler"],"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"}