{"record":{"id":"2d153e0ac75d6eba","repo":"dotnet/reactive","slug":"strings-core-disposables-cant-contain-null","errorCode":null,"errorMessage":"Strings_Core.DISPOSABLES_CANT_CONTAIN_NULL","messagePattern":"Strings_Core\\.DISPOSABLES_CANT_CONTAIN_NULL","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Disposables/StableCompositeDisposable.cs","lineNumber":125,"sourceCode":"                _disposable1.Dispose();\n                _disposable2.Dispose();\n            }\n        }\n\n        private sealed class NAryEnumerable : StableCompositeDisposable\n        {\n            private volatile List<IDisposable>? _disposables;\n\n            public NAryEnumerable(IEnumerable<IDisposable> disposables)\n            {\n                _disposables = new List<IDisposable>(disposables);\n\n                //\n                // Doing this on the list to avoid duplicate enumeration of disposables.\n                //\n                if (_disposables.Contains(null!))\n                {\n                    throw new ArgumentException(Strings_Core.DISPOSABLES_CANT_CONTAIN_NULL, nameof(disposables));\n                }\n            }\n\n            public override bool IsDisposed => _disposables == null;\n\n            public override void Dispose()\n            {\n                var old = Interlocked.Exchange(ref _disposables, null);\n                if (old != null)\n                {\n                    foreach (var d in old)\n                    {\n                        d.Dispose();\n                    }\n                }\n            }\n        }\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Disposables/StableCompositeDisposable.cs#L107-L143","documentation":"StableCompositeDisposable.Create(...) validates its collection of disposables before accepting them. If the passed enumerable contains a null element, an ArgumentException with DISPOSABLES_CANT_CONTAIN_NULL is thrown from the NAryEnumerable constructor. StableCompositeDisposable requires all elements to be non-null so Dispose can iterate and dispose every item without null checks.","triggerScenarios":"Calling StableCompositeDisposable.Create(IEnumerable<IDisposable>) (the NAryEnumerable path) where the enumerable yields a null element, e.g. a List<IDisposable> with a null entry or a LINQ projection producing nulls.","commonSituations":"Building the collection from external or config-driven input where some entries failed to initialize; conditional assignment patterns like cond ? d : null; deserialized collections containing nulls.","solutions":["Filter out nulls before passing: pass disposables.Where(d => d != null).","Fix the code constructing the collection so it never produces null entries.","Assert or log collection contents during construction to locate the null source."],"exampleFix":"// before\nvar composite = StableCompositeDisposable.Create(disposables);\n// after\nvar composite = StableCompositeDisposable.Create(disposables.Where(d => d != null));","handlingStrategy":"validation","validationCode":"if (disposables == null) throw new ArgumentNullException(nameof(disposables));\nif (disposables.Any(d => d == null)) throw new ArgumentException(\"collection contains null\", nameof(disposables));","typeGuard":"bool AllNonNull(IEnumerable<IDisposable?> xs) => xs != null && !xs.Any(d => d is null);","tryCatchPattern":"try { var c = StableCompositeDisposable.Create(disposables); } catch (ArgumentException ex) when (ex.ParamName == nameof(disposables)) { /* sanitize collection and retry */ }","preventionTips":["Sanitize externally sourced collections before composing disposables.","Prefer returning Disposable.Empty over null from factory helpers."],"tags":["argument-validation","null-value","disposable"],"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"}