{"record":{"id":"023fa62e39863b20","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-observer","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'observer')","messagePattern":"Value cannot be null\\. \\(Parameter 'observer'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/AsyncObservable.cs","lineNumber":21,"sourceCode":"// See the LICENSE file in the project root for more information. \n\nusing System.Threading.Tasks;\n\nnamespace System.Reactive\n{\n    public class AsyncObservable<T> : AsyncObservableBase<T>\n    {\n        private readonly Func<IAsyncObserver<T>, ValueTask<IAsyncDisposable>> _subscribeAsync;\n\n        public AsyncObservable(Func<IAsyncObserver<T>, ValueTask<IAsyncDisposable>> subscribeAsync)\n        {\n            _subscribeAsync = subscribeAsync ?? throw new ArgumentNullException(nameof(subscribeAsync));\n        }\n\n        protected override ValueTask<IAsyncDisposable> SubscribeAsyncCore(IAsyncObserver<T> observer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n\n            return _subscribeAsync(observer);\n        }\n    }\n}\n","sourceCodeStart":3,"sourceCodeEnd":27,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/AsyncObservable.cs#L3-L27","documentation":"This ToLookup overload (observer, keySelector, valueSelector, comparer) first validates the downstream observer. A null observer means there is no destination to push the resulting ILookup notifications to, so the operator throws ArgumentNullException(nameof(observer)) synchronously before returning the pipeline.","triggerScenarios":"Calling AsyncObservable.ToLookup(null, keySelector, valueSelector, comparer) — 4-argument overload at ToLookup.cs:134.","commonSituations":"A downstream observer variable not yet initialized; wiring pipelines where the observer is produced by another factory that returned null; constructor-injected observer that was never provided.","solutions":["Pass a valid IAsyncObserver<ILookup<TKey,TValue>> as the first argument","Check that the observer-producing expression actually returns non-null before composing","Create the observer with the library's observer factory APIs instead of passing null"],"exampleFix":"// before\nvar op = AsyncObservable.ToLookup(null, x => x.Key, x => x.Value, comparer);\n// after\nvar sink = AsyncObserver.Create<ILookup<int, string>>(...);\nvar op = AsyncObservable.ToLookup(sink, x => x.Key, x => x.Value, comparer);","handlingStrategy":"validation","validationCode":"if (observer is null) throw new ArgumentNullException(nameof(observer));\n// then compose:\nvar op = AsyncObservable.ToLookup(observer, keySelector, valueSelector, comparer);","typeGuard":"static bool HasSink<T>(IAsyncObserver<T> o) => o != null;","tryCatchPattern":"try\n{\n    var op = AsyncObservable.ToLookup(observer, keySelector, valueSelector, comparer);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"observer\")\n{\n    // create/attach a valid observer before composing\n}","preventionTips":["Always build the downstream observer (AsyncObserver.Create/...) before composing operators","Check DI-injected observer fields for null in constructors","Avoid intermediate variables that may remain null between observer creation and use"],"tags":["argument-null","observer","linq-operator"],"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"}