{"record":{"id":"25b6690a04de9ef5","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-handler-catch","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'handler')","messagePattern":"Value cannot be null\\. \\(Parameter 'handler'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Catch.cs","lineNumber":21,"sourceCode":"// See the LICENSE file in the project root for more information. \n\nusing System.Collections.Generic;\nusing System.Reactive.Disposables;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    // TODO: Implement tail call behavior to flatten Catch chains.\n\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<TSource> Catch<TSource, TException>(this IAsyncObservable<TSource> source, Func<TException, IAsyncObservable<TSource>> handler)\n            where TException : Exception\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (handler == null)\n                throw new ArgumentNullException(nameof(handler));\n\n            return Create(\n                source,\n                handler,\n                static async (source, handler, observer) =>\n                {\n                    var (sink, inner) = AsyncObserver.Catch(observer, handler);\n\n                    var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);\n\n                    return StableCompositeAsyncDisposable.Create(subscription, inner);\n                });\n        }\n\n        public static IAsyncObservable<TSource> Catch<TSource, TException>(this IAsyncObservable<TSource> source, Func<TException, ValueTask<IAsyncObservable<TSource>>> handler)\n            where TException : Exception\n        {\n            if (source == null)","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Catch.cs#L3-L39","documentation":"Catch<TSource,TException> requires a Func<TException, IAsyncObservable<TSource>> that produces the fallback stream; a null handler throws ArgumentNullException at operator construction. Without it the operator cannot react to the exception type.","triggerScenarios":"Calling source.Catch<TException>(null) or Catch(source, (Func<TException, IAsyncObservable<TSource>>)null).","commonSituations":"Handler stored in a nullable field/config that was never set; conditional logic that skips assigning the fallback factory; refactoring swapped the ValueTask overload but cast the lambda to the wrong delegate type resulting in null.","solutions":["Pass a real handler lambda, e.g. ex => AsyncObservable.Return<TValue>(fallbackValue)","Default the handler to one that rethrows or returns Empty if no custom recovery is needed","Null-check the configured handler before composing the operator"],"exampleFix":"// before\nvar result = source.Catch<TimeoutException>(null);\n// after\nvar result = source.Catch<TimeoutException>(ex => AsyncObservable.Empty<int>(Scheduler.Default));","handlingStrategy":"validation","validationCode":"if (handler == null) throw new InvalidOperationException(\"Catch requires a non-null fallback handler\");","typeGuard":"bool HasHandler<TException, TSource>(Func<TException, IAsyncObservable<TSource>> h) => h is not null;","tryCatchPattern":"try { var result = source.Catch<TimeoutException>(handler); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"handler\") { /* supply a default recovery handler */ }","preventionTips":["Default handlers to ex => Empty(scheduler) when no custom recovery exists","Initialize handler fields at construction","Keep sync and async overload usage consistent"],"tags":["argument-null","reactive-extensions","error-handling"],"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"}