dotnet/reactive · error · ArgumentNullException
plans
Error message
plans
What it means
When<TResult>(params QueryablePlan<TResult>[] plans) requires a non-null plans array to match against; the method throws ArgumentNullException("plans") when the array itself is null. Note the params array must exist even if empty (an empty array is accepted, null is not), because the plans are embedded into the Expression.Call for the remote/queryable When operator.
Solutions
- Pass at least one QueryablePlan, or an empty array instead of null: provider.When(Array.Empty<QueryablePlan<TResult>>()).
- Null-check the plans collection and fall back to an empty plan set or an empty result query.
- Fix the code that assembles the plans so it always produces a non-null array.
Example fix
// before QueryablePlan<string>[] plans = BuildPlans(); // null var result = provider.When(plans); // after QueryablePlan<string>[] plans = BuildPlans() ?? Array.Empty<QueryablePlan<string>>(); var result = provider.When(plans);
Defensive patterns
Strategy: validation
Validate before calling
if (plans is null) plans = Array.Empty<QueryablePlan<TResult>>(); var result = provider.When(plans);
Type guard
bool HasPlans<TResult2>(QueryablePlan<TResult2>[]? p) => p is not null;
Try / catch
try { var result = provider.When(plans); }
catch (ArgumentNullException ex) when (ex.ParamName == "plans") { var result = provider.When(Array.Empty<QueryablePlan<TResult>>()); } Prevention
- Pass Array.Empty<T>() rather than null for empty plan sets
- Assemble plans in a method that guarantees a non-null return
- Distinguish 'no plans' (empty array) from 'unset' (null) in your code
When it happens
Trigger: Calling provider.When(null) explicitly, or passing a QueryablePlan<TResult>[] variable that is null (e.g. result of a failed lookup or uninitialized field).
Common situations: Dynamically building plans where the plan collection is assembled conditionally and ends up null at the call site; calling When with a null plans variable instead of an empty array.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/acd3f703ac2ab9c4.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Qbservable.Joins.cs:95
/// <summary>
/// Joins together the results from several patterns.
/// </summary>
/// <typeparam name="TResult">The type of the elements in the result sequence, obtained from the specified patterns.</typeparam>
/// <param name="provider">Query provider used to construct the <see cref="IQbservable{T}"/> data source.</param>
/// <param name="plans">A series of plans created by use of the Then operator on patterns.</param>
/// <returns>An observable sequence with the results from matching several patterns.</returns>
/// <exception cref="ArgumentNullException"><paramref name="provider"/> or <paramref name="plans"/> is null.</exception>
public static IQbservable<TResult> When<TResult>(this IQbservableProvider provider, params QueryablePlan<TResult>[] plans)
{
if (provider == null)
{
throw new ArgumentNullException(nameof(provider));
}
if (plans == null)
{
throw new ArgumentNullException(nameof(plans));
}
return provider.CreateQuery<TResult>(
Expression.Call(
null,
new Func<IQbservableProvider, QueryablePlan<TResult>[], IQbservable<TResult>>(When).Method,
Expression.Constant(provider, typeof(IQbservableProvider)),
Expression.NewArrayInit(
typeof(QueryablePlan<TResult>),
plans.Select(p => p.Expression)
)
)
);
}
/// <summary>
/// Joins together the results from several patterns.
/// </summary>View on GitHub (pinned to 94b5d5ab91)