dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'other')
Error message
Value cannot be null. (Parameter 'other')
What it means
QueryablePattern<TSource1,TSource2>.And<TSource3> extends a two-sequence queryable join pattern with a third observable and throws ArgumentNullException when that sequence is null. This variant builds an expression tree (Expression.Call) for the IQbservable provider, which still requires a non-null source sequence. Raised from the public And method.
Solutions
- Ensure the third observable is non-null before calling And on the queryable pattern.
- Use Observable.Empty<T>()/Observable.Never<T>() as an explicit placeholder sequence.
- Fix the query provider/factory so it returns a valid IQbservable instead of null.
Example fix
// before var qp = pattern.And(thirdSource); // null // after var qp = pattern.And(thirdSource ?? Observable.Empty<TThird>());
Defensive patterns
Strategy: validation
Validate before calling
if (source3 == null) throw new ArgumentNullException(nameof(source3)); var qp = queryablePattern.And(source3);
Type guard
bool HasSource3<T3>(IObservable<T3>? o) => o is not null;
Try / catch
try { qp = queryablePattern.And(source3); }
catch (ArgumentNullException ex) when (ex.ParamName == "other") { log.Error("Null third sequence for QueryablePattern.And"); throw; } Prevention
- Ensure query providers return non-null IQbservable instances
- Default missing streams to Observable.Empty before pattern building
- Enable nullable reference types for Rx-heavy code
When it happens
Trigger: Calling queryablePattern.And(null) on a QueryablePattern<TSource1,TSource2>, e.g. a null IObservable<TSource3> from an unassigned variable or a null-returning provider method.
Common situations: IQbservable-based scenarios (e.g. IQbservable over a remote service) where the third sequence comes from a query provider that returned null; mixing System.Reactive and System.Reactive.Providers code paths in tests.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/6b4df909b745504e.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Joins/QueryablePattern.Generated.cs:40
public class QueryablePattern<TSource1, TSource2> : QueryablePattern
{
internal QueryablePattern(Expression expression)
: base(expression)
{
}
/// <summary>
/// Creates a pattern that matches when all three observable sequences have an available element.
/// </summary>
/// <typeparam name="TSource3">The type of the elements in the third observable sequence.</typeparam>
/// <param name="other">Observable sequence to match with the two previous sequences.</param>
/// <returns>Pattern object that matches when all observable sequences have an available element.</returns>
/// <exception cref="ArgumentNullException"><paramref name="other"/> is null.</exception>
public QueryablePattern<TSource1, TSource2, TSource3> And<TSource3>(IObservable<TSource3> other)
{
if (other == null)
{
throw new ArgumentNullException(nameof(other));
}
var t = typeof(QueryablePattern<TSource1, TSource2>);
var m = t.GetMethod(nameof(And)).MakeGenericMethod(typeof(TSource3));
return new QueryablePattern<TSource1, TSource2, TSource3>(
Expression.Call(
Expression,
m,
Qbservable.GetSourceExpression(other)
)
);
}
/// <summary>
/// Matches when all observable sequences have an available element and projects the elements by invoking the selector function.
/// </summary>
/// <typeparam name="TResult">The type of the elements in the result sequence, returned by the selector function.</typeparam>
/// <param name="selector">Selector that will be invoked for elements in the source sequences.</param>View on GitHub (pinned to 94b5d5ab91)