{"record":{"id":"8bdcebbb607a652e","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-second-8bdceb","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'second')","messagePattern":"Value cannot be null\\. \\(Parameter 'second'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.Zip.cs","lineNumber":1200,"sourceCode":"#pragma warning disable CA1711 // (Don't use Ex suffix.) This has been a public type for many years, so we can't rename it now.\n    public static partial class ObservableEx\n#pragma warning restore CA1711\n    {\n        /// <summary>\n        /// Merges the specified observable sequences into one observable sequence of tuple values whenever all of the observable sequences have produced an element at a corresponding index.\n        /// </summary>\n        /// <typeparam name=\"TFirst\">The type of the elements in the first source sequence.</typeparam>\n        /// <typeparam name=\"TSecond\">The type of the elements in the second source sequence.</typeparam>\n        /// <param name=\"first\">First observable source.</param>\n        /// <param name=\"second\">Second observable source.</param>\n        /// <returns>An observable sequence containing the result of combining elements of the sources using tuple values.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"first\"/> or <paramref name=\"second\"/> is null.</exception>\n        public static IObservable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(this IObservable<TFirst> first, IObservable<TSecond> second)\n        {\n            if (first == null)\n                throw new ArgumentNullException(nameof(first));\n            if (second == null)\n                throw new ArgumentNullException(nameof(second));\n\n            return s_impl.Zip(first, second);\n        }\n\n        /// <summary>\n        /// Merges the specified observable sequences into one observable sequence of tuple values whenever all of the observable sequences have produced an element at a corresponding index.\n        /// </summary>\n        /// <typeparam name=\"TFirst\">The type of the elements in the first source sequence.</typeparam>\n        /// <typeparam name=\"TSecond\">The type of the elements in the second source sequence.</typeparam>\n        /// <typeparam name=\"TThird\">The type of the elements in the third source sequence.</typeparam>\n        /// <param name=\"first\">First observable source.</param>\n        /// <param name=\"second\">Second observable source.</param>\n        /// <param name=\"third\">Third observable source.</param>\n        /// <returns>An observable sequence containing the result of combining elements of the sources using tuple values.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"first\"/> or <paramref name=\"second\"/> or <paramref name=\"third\"/> is null.</exception>\n        public static IObservable<(TFirst First, TSecond Second, TThird Third)> Zip<TFirst, TSecond, TThird>(this IObservable<TFirst> first, IObservable<TSecond> second, IObservable<TThird> third)\n        {\n            if (first == null)","sourceCodeStart":1182,"sourceCodeEnd":1218,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.Zip.cs#L1182-L1218","documentation":"System.Reactive's public Zip<TFirst, TSecond> extension method explicitly validates its arguments before delegating to the internal implementation, throwing ArgumentNullException when the second source sequence is null. Rx operators require non-null sources because the internal pipeline calls Subscribe on every sequence and cannot recover from a null. This is an immediate, fail-fast argument validation, not a runtime failure of the query.","triggerScenarios":"Calling Observable.Zip(first, null) or IObservable.Zip(first, second) where the second IObservable<TSecond> variable is null (e.g. an uninitialized field, a failed lookup, or a method returned null instead of Observable.Empty).","commonSituations":"Passing a sequence obtained from a dictionary lookup or optional dependency that turned out to be null; a factory method returning null instead of an empty observable; refactoring that removed a default sequence assignment.","solutions":["Ensure the second observable is assigned before calling Zip (check for uninitialized/failed factory results).","Substitute Observable.Empty<TSecond>() or Observable.Never<TSecond>() when 'no sequence' is the intended semantic.","Wrap the call site in a null check and throw a meaningful domain-specific error or log which source was missing."],"exampleFix":"// before\nvar zipped = xs.Zip(ys); // ys is null\n// after\nvar zipped = xs.Zip(ys ?? Observable.Empty<int>());","handlingStrategy":"validation","validationCode":"if (first == null) throw new ArgumentNullException(nameof(first));\nif (second == null) throw new ArgumentNullException(nameof(second));\nvar zipped = first.Zip(second);","typeGuard":"bool IsNonNull<T>(IObservable<T> s) => s is not null;","tryCatchPattern":"try { var zipped = first.Zip(second); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"second\") { /* log and use fallback source */ }","preventionTips":["Never let factory/lookup methods return null observables; return Observable.Empty instead.","Null-check all source sequences before composing multi-source queries.","Use nullable reference types (IObservable<T>?) to surface unassigned streams at compile time."],"tags":["reactive","argument-null","zip"],"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"}