{"record":{"id":"ddcbf01e9de50cf7","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-disposable","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'disposable')","messagePattern":"Value cannot be null\\. \\(Parameter 'disposable'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Disposables/CompositeAsyncDisposable.cs","lineNumber":42,"sourceCode":"        {\n            if (disposables == null)\n                throw new ArgumentNullException(nameof(disposables));\n\n            _disposables = new List<IAsyncDisposable>(disposables);\n        }\n\n        public CompositeAsyncDisposable(IEnumerable<IAsyncDisposable> disposables)\n        {\n            if (disposables == null)\n                throw new ArgumentNullException(nameof(disposables));\n\n            _disposables = new List<IAsyncDisposable>(disposables);\n        }\n\n        public async ValueTask AddAsync(IAsyncDisposable disposable)\n        {\n            if (disposable == null)\n                throw new ArgumentNullException(nameof(disposable));\n\n            var shouldDispose = false;\n\n            using (await _gate.LockAsync().ConfigureAwait(false))\n            {\n                if (_disposed)\n                {\n                    shouldDispose = true;\n                }\n                else\n                {\n                    _disposables.Add(disposable);\n                }\n            }\n\n            if (shouldDispose)\n            {\n                await disposable.DisposeAsync().ConfigureAwait(false);","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Disposables/CompositeAsyncDisposable.cs#L24-L60","documentation":"CompositeAsyncDisposable.AddAsync registers an IAsyncDisposable to be disposed when the composite is disposed. A null argument is rejected immediately with ArgumentNullException naming 'disposable', because the composite would otherwise throw during DisposeAsync when iterating its children.","triggerScenarios":"await composite.AddAsync(null) — typically a factory/method that returned null instead of a disposable, or a nullable field not yet initialized.","commonSituations":"Conditional resource creation that skips assignment; passing the result of a TryGet-style API that yields null; refactoring where a disposable was removed but call sites still add it.","solutions":["Ensure a non-null IAsyncDisposable is produced before calling AddAsync","Skip the AddAsync call when the value is null","Substitute AsyncDisposable.Nop for a null disposable"],"exampleFix":"// before\nvar d = CreateResource(); // may return null\nawait composite.AddAsync(d);\n// after\nvar d = CreateResource();\nif (d != null)\n    await composite.AddAsync(d);","handlingStrategy":"type-guard","validationCode":"if (disposable != null) await composite.AddAsync(disposable);","typeGuard":"bool IsAddable(IAsyncDisposable? disposable) => disposable is not null;","tryCatchPattern":"try { await composite.AddAsync(disposable); } catch (ArgumentNullException ex) when (ex.ParamName == \"disposable\") { await composite.AddAsync(AsyncDisposable.Nop); }","preventionTips":["Guard factory results for null before adding to a composite","Substitute AsyncDisposable.Nop for optional disposables","Avoid methods that return null disposables; return Nop or throw at the source"],"tags":["argument-null","composite-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"}