dotnet/reactive · error · ArgumentException

Invalid expression tree type.

Error message

Invalid expression tree type.

What it means

ObservableQueryProvider.CreateQuery<TResult> verifies that the expression tree's static Type is assignable to IObservable<TResult> and throws ArgumentException (INVALID_TREE_TYPE, message 'Invalid expression tree type.') otherwise. Qbservable providers can only execute queries rooted in an observable sequence.

Solutions

  1. Build the query from an expression rooted at an IQbservable/IObservable<TResult> matching the requested TResult
  2. Fix the generic type parameter so TResult matches the observable element type of the expression
  3. If porting LINQ-to-Objects code, rewrite the query against the Qbservable provider's AsQbservable entry point instead of passing IQueryable expressions

Example fix

// before
Expression expr = Expression.Constant(list); // System.Collections.Generic.List<int>
var q = provider.CreateQuery<int>(expr);
// after
Expression expr = Expression.Constant(observableInts); // IObservable<int>
var q = provider.CreateQuery<int>(expr);
Defensive patterns

Strategy: validation

Validate before calling

if (expression != null && !typeof(IObservable<TResult>).IsAssignableFrom(expression.Type)) throw new InvalidOperationException("expression tree must be rooted in IObservable<T>");

Try / catch

try { provider.CreateQuery<T>(expression); } catch (ArgumentException ex) { /* rebuild tree with correct IObservable<T> root */ }

Prevention

When it happens

Trigger: Calling CreateQuery<TResult>(expression) (ObservableQuery.cs:24) with an expression whose Type is not IObservable<TResult> — e.g. an expression representing IQueryable, a raw value, or a different generic result type than requested.

Common situations: Mixing IQueryable and IQbservable trees (passing an EF/IQueryable expression into a Qbservable provider); calling CreateQuery<int> on a tree typed IObservable<long>; hand-built expression trees with the wrong Type.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/ff22f5cc94941723. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/ObservableQuery.cs:30

using System.Reflection;

namespace System.Reactive
{
#if HAS_TRIMMABILITY_ATTRIBUTES
    [RequiresUnreferencedCode(Constants_Core.AsQueryableTrimIncompatibilityMessage)]
#endif
    internal class ObservableQueryProvider : IQbservableProvider, IQueryProvider
    {
        public IQbservable<TResult> CreateQuery<TResult>(Expression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            if (!typeof(IObservable<TResult>).IsAssignableFrom(expression.Type))
            {
                throw new ArgumentException(Strings_Providers.INVALID_TREE_TYPE, nameof(expression));
            }

            return new ObservableQuery<TResult>(expression);
        }

        IQueryable<TElement> IQueryProvider.CreateQuery<TElement>(Expression expression)
        {
            //
            // Here we're on the edge between IQbservable and IQueryable for the local
            // execution case. E.g.:
            //
            //   observable.AsQbservable().<operators>.ToQueryable()
            //
            // This should be turned into a local execution, with the push-to-pull
            // adapter in the middle, so we rewrite to:
            //
            //   observable.AsQbservable().<operators>.ToEnumerable().AsQueryable()
            //

View on GitHub (pinned to 94b5d5ab91)