{"record":{"id":"0203a799189aeeb1","repo":"dotnet/reactive","slug":"source-merge","errorCode":null,"errorMessage":"source","messagePattern":"source","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Merge.cs","lineNumber":18,"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        // TODO: Add Merge with max concurrency and IEnumerable<T>-based overloads.\n\n        public static IAsyncObservable<TSource> Merge<TSource>(this IAsyncObservable<IAsyncObservable<TSource>> source)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n\n            return Create<TSource>(async observer =>\n            {\n                var (sink, cancel) = AsyncObserver.Merge(observer);\n\n                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);\n\n                return StableCompositeAsyncDisposable.Create(subscription, cancel);\n            });\n        }\n    }\n\n    public partial class AsyncObserver\n    {\n        public static (IAsyncObserver<IAsyncObservable<TSource>>, IAsyncDisposable) Merge<TSource>(IAsyncObserver<TSource> observer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Merge.cs#L1-L36","documentation":"Merge's public extension throws ArgumentNullException when the source observable of observables is null. Merge flattens a stream of inner streams into one; with no outer source there is nothing to subscribe. The check runs before Create builds the subscription pipeline.","triggerScenarios":"Calling nullSource.Merge<TSource>() — e.g. an IAsyncObservable<IAsyncObservable<T>> variable that is null because an upstream factory returned null.","commonSituations":"Chaining Merge after an operator that returned null; conditional pipeline construction leaving the source unassigned; deserialized/configured sources that failed to resolve.","solutions":["Ensure the outer source is a valid IAsyncObservable<IAsyncObservable<TSource>> before calling Merge","Check the preceding operator/factory in the chain for null returns","If sources may be absent, default to AsyncObservable.Empty<IAsyncObservable<TSource>>()"],"exampleFix":"// before\nIAsyncObservable<IAsyncObservable<int>> sources = GetSources(); // returns null\nvar merged = sources.Merge();\n// after\nvar merged = (sources ?? AsyncObservable.Empty<IAsyncObservable<int>>()).Merge();","handlingStrategy":"validation","validationCode":"if (sources == null) throw new InvalidOperationException(\"Outer source for Merge must not be null\");","typeGuard":"bool HasSource<T>(IAsyncObservable<T> s) => s is not null;","tryCatchPattern":"try { var merged = sources.Merge(); } catch (ArgumentNullException ex) when (ex.ParamName == \"source\") { /* fall back to empty source */ }","preventionTips":["Verify upstream operators/factories never return null","Default missing sources to AsyncObservable.Empty","Chain Merge only from known-good producers"],"tags":["argument-null","merge","async-rx"],"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"}