{"record":{"id":"9216dc2ad91a4bf7","repo":"dotnet/reactive","slug":"argument-cannot-be-null-parameter-name-source-foreachasync","errorCode":null,"errorMessage":"Argument cannot be null (Parameter name: source)","messagePattern":"Argument cannot be null \\(Parameter name: source\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/ForEachAsync.cs","lineNumber":16,"sourceCode":"﻿// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT License.\n// See the LICENSE file in the project root for more information. \n\nusing System.Reactive.Disposables;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Action<TSource> onNext, CancellationToken token = default)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (onNext == null)\n                throw new ArgumentNullException(nameof(onNext));\n\n            return ForEachAsyncCore(source, (x, i) => { onNext(x); return Task.CompletedTask; }, token);\n        }\n\n        public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task> onNext, CancellationToken token = default)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (onNext == null)\n                throw new ArgumentNullException(nameof(onNext));\n\n            return ForEachAsyncCore(source, (x, i) => onNext(x), token);\n        }\n\n        public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Action<TSource, int> onNext, CancellationToken token = default)\n        {","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/ForEachAsync.cs#L1-L34","documentation":"ForEachAsync(IAsyncObservable<TSource>, Action<TSource>, CancellationToken) throws ArgumentNullException because the source observable is null. ForEachAsync is an extension method, but extension methods can be invoked with a null receiver (including explicit static calls), so the null check names 'source'. Validation happens immediately, before the subscription work begins.","triggerScenarios":"Calling observable.ForEachAsync(onNext) where observable is null — e.g. a method that returns IAsyncObservable<T> and returned null, or an explicit AsyncObservable.ForEachAsync(null, action) call.","commonSituations":"Factory/DI methods that return null instead of an empty observable; caching a subscription source in a field that was never initialized; optional sources in configuration that were not created.","solutions":["Ensure the source observable is created (e.g. AsyncObservable.Return/FromEvent/Empty) before iterating it.","Guard: if (source == null) return Task.CompletedTask; when absence legitimately means 'nothing to observe'.","Fix the producer that returns null so it returns AsyncObservable.Empty<TSource>() instead.","If using an explicit static call, pass a real IAsyncObservable<TSource> instance."],"exampleFix":"// before\nvar source = _registry.TryGet(key); // returns null when missing\nawait source.ForEachAsync(x => Handle(x));\n\n// after\nvar source = _registry.TryGet(key);\nif (source != null)\n    await source.ForEachAsync(x => Handle(x));","handlingStrategy":"validation","validationCode":"if (source == null)\n    return Task.CompletedTask; // nothing to observe\nreturn source.ForEachAsync(onNext, token);","typeGuard":"static bool IsNonNullObservable<T>(IAsyncObservable<T> s) => s is not null;","tryCatchPattern":"try { await source.ForEachAsync(onNext, token); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"source\") { /* source factory returned null — treat as no data or rethrow with context */ }","preventionTips":["Make observable factories throw or return Empty, never null.","Guard extension-method calls where the receiver may be null.","Enable nullable reference types so null receivers are flagged."],"tags":["asyncrx","argument-null","foreachasync","extension-method"],"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"}