{"record":{"id":"ec2ac4179696668a","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-item","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'item')","messagePattern":"Value cannot be null\\. \\(Parameter 'item'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Disposables/CompositeDisposable.cs","lineNumber":165,"sourceCode":"\n            return (list, list.Count);\n        }\n\n        /// <summary>\n        /// Gets the number of disposables contained in the <see cref=\"CompositeDisposable\"/>.\n        /// </summary>\n        public int Count => Volatile.Read(ref _count);\n\n        /// <summary>\n        /// Adds a disposable to the <see cref=\"CompositeDisposable\"/> or disposes the disposable if the <see cref=\"CompositeDisposable\"/> is disposed.\n        /// </summary>\n        /// <param name=\"item\">Disposable to add.</param>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"item\"/> is <c>null</c>.</exception>\n        public void Add(IDisposable item)\n        {\n            if (item == null)\n            {\n                throw new ArgumentNullException(nameof(item));\n            }\n\n            lock (_gate)\n            {\n                if (!_disposed)\n                {\n                    if (_disposables is List<IDisposable?> listDisposables)\n                    {\n                        listDisposables.Add(item);\n\n                        // Once we get to thousands of items (which happens with wide fan-out/in configurations)\n                        // the cost of linear search becomes too high. We switch to a dictionary at that point.\n                        // See https://github.com/dotnet/reactive/issues/2005\n                        if (listDisposables.Count > MaximumLinearSearchThreshold)\n                        {\n                            // If we've blown through this threshold, chances are there's more to come,\n                            // so allocate some more spare capacity.\n                            var dictionary = new Dictionary<IDisposable, int>(listDisposables.Count + (listDisposables.Count / 4));","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Disposables/CompositeDisposable.cs#L147-L183","documentation":"CompositeDisposable.Add requires a non-null IDisposable; a null item has no Dispose behavior and would break Remove/Dispose bookkeeping, so ArgumentNullException with parameter name 'item' is thrown before the lock is taken. Callers listed (Subscribe, DisposeWith, Run, etc.) are typical upstream paths where a null disposable flows in.","triggerScenarios":"composite.Add(null), or passing the result of a Subscribe/handler-registration helper that returned null (e.g. a hand-rolled Subscribe returning null instead of Disposable.Empty).","commonSituations":"Manual subscription management where teardown registration methods return null on failure; conditional code paths assigning null to a disposable variable; interop with other libraries returning null tokens.","solutions":["Never return null from helper methods that produce disposables — return Disposable.Empty instead","Check for null before adding: if (d != null) composite.Add(d);","Ensure your ISubscribe-like implementations follow the Rx contract of returning a non-null IDisposable"],"exampleFix":"// before\ncomposite.Add(SubscribeToSomething()); // may return null\n// after\nvar d = SubscribeToSomething();\nif (d != null) composite.Add(d);","handlingStrategy":"type-guard","validationCode":"if (item != null) composite.Add(item);","typeGuard":"void AddSafe(CompositeDisposable cd, IDisposable? item) { if (item is not null) cd.Add(item); }","tryCatchPattern":"try { composite.Add(d); }\ncatch (ArgumentNullException) { /* log: subscription returned null disposable */ }","preventionTips":["Return Disposable.Empty instead of null from subscribe-like helpers","Use the is not null pattern at call sites","Centralize Add behind a helper that null-checks","Follow the Rx contract: Subscribe must return a non-null IDisposable"],"tags":["rx","disposable","null-argument"],"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"}