{"record":{"id":"79c35d5ddd836088","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-oncompleted-asyncqueryableex","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'onCompleted')","messagePattern":"Value cannot be null\\. \\(Parameter 'onCompleted'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.cs","lineNumber":1060,"sourceCode":"            return source.Provider.CreateQuery<TSource>(Expression.Call(Do__TSource__4__0(typeof(TSource)), source.Expression, onNext, onError, Expression.Constant(onCompleted, typeof(Action))));\n        }\n\n        private static MethodInfo? s_Do__TSource__4__1;\n        \n        private static MethodInfo Do__TSource__4__1(Type TSource) =>\n            (s_Do__TSource__4__1 ??\n            (s_Do__TSource__4__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, Task>>, Expression<Func<Exception, CancellationToken, Task>>, Expression<Func<CancellationToken, Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);\n\n        public static IAsyncQueryable<TSource> Do<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, Task>> onNext, Expression<Func<Exception, CancellationToken, Task>> onError, Expression<Func<CancellationToken, Task>> onCompleted)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (onNext == null)\n                throw new ArgumentNullException(nameof(onNext));\n            if (onError == null)\n                throw new ArgumentNullException(nameof(onError));\n            if (onCompleted == null)\n                throw new ArgumentNullException(nameof(onCompleted));\n\n            return source.Provider.CreateQuery<TSource>(Expression.Call(Do__TSource__4__1(typeof(TSource)), source.Expression, onNext, onError, onCompleted));\n        }\n\n        private static MethodInfo? s_Do__TSource__4__2;\n        \n        private static MethodInfo Do__TSource__4__2(Type TSource) =>\n            (s_Do__TSource__4__2 ??\n            (s_Do__TSource__4__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, Task>>, Expression<Func<Exception, Task>>, Expression<Func<Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);\n\n        public static IAsyncQueryable<TSource> Do<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, Task>> onNext, Expression<Func<Exception, Task>> onError, Expression<Func<Task>> onCompleted)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (onNext == null)\n                throw new ArgumentNullException(nameof(onNext));\n            if (onError == null)\n                throw new ArgumentNullException(nameof(onError));","sourceCodeStart":1042,"sourceCodeEnd":1078,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.cs#L1042-L1078","documentation":"ArgumentNullException thrown by the AsyncQueryableEx.Do<TSource> overload taking onNext/onError/onCompleted handlers when the onCompleted expression is null. Do builds a query operator whose three handler arguments are translated into the provider expression tree, so each must be non-null and is validated in order. The message names 'onCompleted'.","triggerScenarios":"Calling Do(source, onNext, onError, null) — typically because source/onNext/onError were validated earlier and only onCompleted was left null, e.g. a partial-handler factory that supplies only some callbacks.","commonSituations":"Logging/tap pipelines where the completion handler was deemed optional; adapters mapping Rx-style observers to queryable Do with a missing onCompleted; code generators emitting null for empty handlers.","solutions":["Pass a no-op completion expression: () => Task.CompletedTask","If only onNext is needed, use the single-handler Do overload instead","Fix handler-factory code so it emits a completed-task lambda rather than null for onCompleted","Wrap observer adaptation to always materialize all three handlers"],"exampleFix":"// before\nquery.Do(x => Log(x), e => LogErr(e), null);\n// after\nquery.Do(x => Log(x), e => LogErr(e), () => Task.CompletedTask);","handlingStrategy":"validation","validationCode":"if (onCompleted is null) onCompleted = () => Task.CompletedTask;","typeGuard":"static bool HasCompleted(Expression<Func<Task>>? h) => h is not null;","tryCatchPattern":"try { q = source.Do(onNext, onError, onCompleted); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"onCompleted\") { q = source.Do(onNext, onError, () => Task.CompletedTask); }","preventionTips":["Treat all three Do handlers as required; use () => Task.CompletedTask for no-ops","Use the smaller Do overloads when fewer handlers are needed","Coalesce optional handlers with ?? before calling Do"],"tags":["csharp","null-argument","expression-tree","do-operator"],"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"}