{"record":{"id":"011bf3f6971a9e20","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-oncompleted-anonymousobserver","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'onCompleted')","messagePattern":"Value cannot be null\\. \\(Parameter 'onCompleted'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/AnonymousObserver.cs","lineNumber":28,"sourceCode":"    /// <typeparam name=\"T\">The type of the elements in the sequence.</typeparam>\n    public sealed class AnonymousObserver<T> : ObserverBase<T>\n    {\n        private readonly Action<T> _onNext;\n        private readonly Action<Exception> _onError;\n        private readonly Action _onCompleted;\n\n        /// <summary>\n        /// Creates an observer from the specified <see cref=\"IObserver{T}.OnNext(T)\"/>, <see cref=\"IObserver{T}.OnError(Exception)\"/>, and <see cref=\"IObserver{T}.OnCompleted()\"/> actions.\n        /// </summary>\n        /// <param name=\"onNext\">Observer's <see cref=\"IObserver{T}.OnNext(T)\"/> action implementation.</param>\n        /// <param name=\"onError\">Observer's <see cref=\"IObserver{T}.OnError(Exception)\"/> action implementation.</param>\n        /// <param name=\"onCompleted\">Observer's <see cref=\"IObserver{T}.OnCompleted()\"/> action implementation.</param>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"onNext\"/> or <paramref name=\"onError\"/> or <paramref name=\"onCompleted\"/> is <c>null</c>.</exception>\n        public AnonymousObserver(Action<T> onNext, Action<Exception> onError, Action onCompleted)\n        {\n            _onNext = onNext ?? throw new ArgumentNullException(nameof(onNext));\n            _onError = onError ?? throw new ArgumentNullException(nameof(onError));\n            _onCompleted = onCompleted ?? throw new ArgumentNullException(nameof(onCompleted));\n        }\n\n        /// <summary>\n        /// Creates an observer from the specified <see cref=\"IObserver{T}.OnNext(T)\"/> action.\n        /// </summary>\n        /// <param name=\"onNext\">Observer's <see cref=\"IObserver{T}.OnNext(T)\"/> action implementation.</param>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"onNext\"/> is <c>null</c>.</exception>\n        public AnonymousObserver(Action<T> onNext)\n            : this(onNext, Stubs.Throw, Stubs.Nop)\n        {\n        }\n\n        /// <summary>\n        /// Creates an observer from the specified <see cref=\"IObserver{T}.OnNext(T)\"/> and <see cref=\"IObserver{T}.OnError(Exception)\"/> actions.\n        /// </summary>\n        /// <param name=\"onNext\">Observer's <see cref=\"IObserver{T}.OnNext(T)\"/> action implementation.</param>\n        /// <param name=\"onError\">Observer's <see cref=\"IObserver{T}.OnError(Exception)\"/> action implementation.</param>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"onNext\"/> or <paramref name=\"onError\"/> is <c>null</c>.</exception>","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/AnonymousObserver.cs#L10-L46","documentation":"The AnonymousObserver constructor throws ArgumentNullException when the onCompleted action is null. Along with onNext and onError, the completion callback must be a real delegate because Rx will invoke it when the sequence finishes; null is rejected at construction time.","triggerScenarios":"Calling new AnonymousObserver<T>(onNext, onError, null) or source.Subscribe(onNext, onError, onCompleted: null), typically when the completion handler is fetched from a nullable delegate or omitted during refactor.","commonSituations":"UI subscriptions that only care about values and errors; dynamically composed handlers where the completed callback was never assigned; migration from Subscribe overloads that defaulted handlers to ones that require all three.","solutions":["Supply a real onCompleted action, e.g. () => Console.WriteLine(\"done\")","If completion is irrelevant, pass a no-op: () => { }","Default the completion callback before subscribing"],"exampleFix":"// before\nvar sub = source.Subscribe(x => Handle(x), ex => Log(ex), null);\n// after\nvar sub = source.Subscribe(x => Handle(x), ex => Log(ex), () => Done());","handlingStrategy":"type-guard","validationCode":"// C#\nAction? onCompleted = ResolveCompleted();\nif (onCompleted is null)\n    onCompleted = () => { };\nvar sub = source.Subscribe(x => Handle(x), ex => Log(ex), onCompleted);","typeGuard":"bool HasCompleted(Action? a) => a is not null;","tryCatchPattern":"try { var sub = source.Subscribe(onNext, onError, onCompleted); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"onCompleted\")\n{\n    // supply a no-op completion handler\n}","preventionTips":["Use the Subscribe(onNext, onError) overload when completion is irrelevant","Default completion fields to () => { }","Never pass null positionally for the last Subscribe argument"],"tags":["rx","observer","subscribe","null-argument"],"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"}