{"record":{"id":"f28236623b2486dc","repo":"dotnet/reactive","slug":"argumentnullexception-nameof-plans","errorCode":null,"errorMessage":"ArgumentNullException(nameof(plans))","messagePattern":"ArgumentNullException\\(nameof\\(plans\\)\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/When.cs","lineNumber":17,"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.Collections.Generic;\nusing System.Reactive.Disposables;\nusing System.Reactive.Joins;\nusing System.Threading;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<TResult> When<TResult>(IEnumerable<AsyncPlan<TResult>> plans)\n        {\n            if (plans == null)\n                throw new ArgumentNullException(nameof(plans));\n\n            return Create<TResult>(async observer =>\n            {\n                var externalSubscriptions = new Dictionary<object, IAsyncJoinObserver>();\n                var gate = new AsyncGate();\n                var activePlans = new List<ActiveAsyncPlan>();\n\n                var outputObserver = AsyncObserver.Create<TResult>(\n                    observer.OnNextAsync,\n                    async ex =>\n                    {\n                        foreach (var subscription in externalSubscriptions.Values)\n                        {\n                            await subscription.DisposeAsync().ConfigureAwait(false);\n                        }\n\n                        await observer.OnErrorAsync(ex).ConfigureAwait(false);\n                    },","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/When.cs#L1-L35","documentation":"When composes concurrent AsyncPlan<TResult> streams using join semantics. It validates the plans sequence eagerly and throws ArgumentNullException with param name 'plans' when the IEnumerable<AsyncPlan<TResult>> is null. The throw occurs synchronously when the query is built, not when it is subscribed.","triggerScenarios":"Calling AsyncObservable.When<TResult>(null) — a null plans collection, e.g. from a variable that was never assigned or a method returning null.","commonSituations":"Building plan lists dynamically (loops adding plans) where the list was never initialized; a factory method returning null instead of an empty collection; LINQ chains that can yield null.","solutions":["Pass a non-null IEnumerable<AsyncPlan<TResult>>, even an empty one.","Initialize the plan collection before calling When (e.g. new List<AsyncPlan<int>>()).","Coalesce at the call site: plans ?? Enumerable.Empty<AsyncPlan<int>>() if empty is acceptable."],"exampleFix":"// before\nList<AsyncPlan<int>> plans = null;\nvar result = AsyncObservable.When(plans);\n// after\nvar plans = new List<AsyncPlan<int>> { plan1, plan2 };\nvar result = AsyncObservable.When(plans);","handlingStrategy":"validation","validationCode":"if (plans == null)\n    plans = Enumerable.Empty<AsyncPlan<TResult>>(); // or throw a descriptive error","typeGuard":"bool HasPlans<TResult>(IEnumerable<AsyncPlan<TResult>> plans) => plans is not null;","tryCatchPattern":"try\n{\n    var obs = AsyncObservable.When(plans);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"plans\")\n{\n    // fall back to AsyncObservable.Empty<TResult>() or log a plan-building bug\n}","preventionTips":["Initialize plan collections at declaration: var plans = new List<AsyncPlan<T>>();","Have plan-builder methods return empty collections instead of null.","Guard dynamic plan assembly with a null check before calling When."],"tags":["argument-null","linq-operator","async-rx","when-plans"],"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"}