dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'begin')
Error message
Value cannot be null. (Parameter 'begin')
What it means
Observable.FromAsyncPattern<TResult> (the legacy Begin/End APM wrapper, marked obsolete in favor of Task-based APIs) eagerly validates the begin delegate and throws ArgumentNullException when it is null. The check runs when the wrapper function is created, before it is invoked or subscribed to.
Solutions
- Pass valid begin/end delegates, e.g. Observable.FromAsyncPattern(stream.BeginRead, stream.EndRead).
- Prefer the modern alternative: use Observable.FromTask/ToObservable with Task-based APIs (TaskFactory.FromAsync or native *Async methods) instead of the obsolete FromAsyncPattern.
- If delegates are resolved dynamically, null-check the MethodInfo/delegate result before calling the factory.
Example fix
// before var read = Observable.FromAsyncPattern<byte[]>(beginMethod, endMethod); // beginMethod == null // after var read = Observable.FromAsyncPattern<byte[]>(stream.BeginRead, stream.EndRead); // or prefer task-based: var read = () => Observable.FromTask(stream.ReadAsync(buffer, offset, count));
Defensive patterns
Strategy: validation
Validate before calling
if (begin == null || end == null)
throw new ArgumentNullException(nameof(begin), "FromAsyncPattern requires non-null begin/end delegates");
var read = begin != null && end != null ? Observable.FromAsyncPattern(begin, end) : null; Type guard
bool HasApmPair(Func<AsyncCallback, object?, IAsyncResult>? begin, Func<IAsyncResult, TResult>? end)
=> begin != null && end != null; Try / catch
try { var op = Observable.FromAsyncPattern(begin, end); }
catch (ArgumentNullException ex) when (ex.ParamName == "begin") { /* repair Begin-method reference */ } Prevention
- Avoid the obsolete APM wrapper; prefer Task-based APIs with Observable.FromTask.
- If resolving Begin/End methods via reflection, assert both delegates before wiring.
- Use method groups (stream.BeginRead, stream.EndRead) so the compiler verifies the pair.
When it happens
Trigger: Calling Observable.FromAsyncPattern(begin, end) with a null begin delegate — e.g. a BeginXxx method reference obtained via reflection that failed, or an uninitialized delegate variable, while end may also be null (its check follows).
Common situations: Migrating legacy APM code where Begin/End pairs are wired dynamically; reflection-based method lookup returning null when the method name/signature changed across framework versions; obsolete-API usage that was only partially ported.
Related errors
- Value cannot be null. (Parameter 'onNextAsync')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'actionAsync')
- Value cannot be null. (Parameter 'onErrorAsync')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/a50287a9faf67046.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs:31
#region FromAsyncPattern
#region Func
/// <summary>
/// Converts a Begin/End invoke function pair into an asynchronous function.
/// </summary>
/// <typeparam name="TResult">The type of the result returned by the end delegate.</typeparam>
/// <param name="begin">The delegate that begins the asynchronous operation.</param>
/// <param name="end">The delegate that ends the asynchronous operation.</param>
/// <returns>Function that can be used to start the asynchronous operation and retrieve the result as an observable sequence.</returns>
/// <exception cref="ArgumentNullException"><paramref name="begin"/> or <paramref name="end"/> is null.</exception>
/// <remarks>Each invocation of the resulting function will cause the asynchronous operation to be started. Subscription to the resulting sequence has no observable side-effect, and each subscription will produce the asynchronous operation's result.</remarks>
[Obsolete(Constants_Linq.UseTaskFromAsyncPattern)]
public static Func<IObservable<TResult>> FromAsyncPattern<TResult>(Func<AsyncCallback, object?, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
{
if (begin == null)
{
throw new ArgumentNullException(nameof(begin));
}
if (end == null)
{
throw new ArgumentNullException(nameof(end));
}
return s_impl.FromAsyncPattern(begin, end);
}
/// <summary>
/// Converts a Begin/End invoke function pair into an asynchronous function.
/// </summary>
/// <typeparam name="TArg1">The type of the first argument passed to the begin delegate.</typeparam>
/// <typeparam name="TResult">The type of the result returned by the end delegate.</typeparam>
/// <param name="begin">The delegate that begins the asynchronous operation.</param>
/// <param name="end">The delegate that ends the asynchronous operation.</param>
/// <returns>Function that can be used to start the asynchronous operation and retrieve the result as an observable sequence.</returns>View on GitHub (pinned to 94b5d5ab91)