dotnet/efcore · error · NotSupportedException

Unsupported type: {type}

Error message

Unsupported type: {type}

What it means

Thrown in PrecompiledQueryCodeGenerator.GetTypeSymbol (line 1263) when asked to map a runtime System.Type to a Roslyn ITypeSymbol but the type is by-ref, a pointer, a generic parameter, or a ref-like struct. These categories cannot be embedded in generated interceptor source, so GetTypeSymbol rejects them up front with NotSupportedException before attempting metadata lookup.

Source

Thrown at src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs:1263

                expression = methodCallExpression.Object;
                continue;
            }

            throw new InvalidOperationException(RelationalStrings.InvalidArgumentToExecuteUpdate);
        }

        // The expression tree is nested inside-out (last SetProperty call is the outermost node),
        // so setters were added in reverse order. Reverse to restore source code order.
        var settersArray = settersBuilder.BuildSettersExpression();
        return Expression.NewArrayInit(settersArray.Type.GetElementType()!, settersArray.Expressions.Reverse());
    }

    private static ITypeSymbol GetTypeSymbol(Compilation compilation, Type type)
    {
        if (type.IsByRef || type.IsPointer || type.IsGenericParameter || type.IsByRefLike)
        {
            throw new NotSupportedException($"Unsupported type: {type}");
        }

        if (type.IsArray)
        {
            var elementSymbol = GetTypeSymbol(compilation, type.GetElementType()!);
            return compilation.CreateArrayTypeSymbol(elementSymbol, type.GetArrayRank());
        }

        if (type.IsGenericType && !type.IsGenericTypeDefinition)
        {
            var genericDefinition = (INamedTypeSymbol)GetTypeSymbol(
                compilation,
                type.GetGenericTypeDefinition());

            var typeArguments = type
                .GetGenericArguments()
                .Select(t => GetTypeSymbol(compilation, t))
                .ToArray();

View on GitHub (pinned to dbf9771522)

Solutions

  1. Avoid queries/operators whose signatures use ref, pointer, generic-parameter, or ref-struct types when precompiling.
  2. Refactor to use a concrete, embeddable type (e.g. an array or IReadOnlyList<T> instead of Span<T>) for the relevant operation.
  3. Exclude the query using such a type from precompilation.
  4. If the type comes from a captured variable, materialize it to a normal reference type before the precompiled query.
Defensive patterns

Strategy: validation

Validate before calling

// Reject unsupported type categories before code generation
static bool IsEmbeddableType(Type t)
    => !t.IsByRef && !t.IsPointer && !t.IsGenericParameter && !t.IsByRefLike;

Type guard

static bool IsEmbeddableType(Type t)
    => !t.IsByRef && !t.IsPointer && !t.IsGenericParameter && !t.IsByRefLike;

Try / catch

try { /* generate */ }
catch (NotSupportedException ex) when (ex.Message.StartsWith("Unsupported type"))
{ /* switch to an embeddable type or exclude the query */ }

Prevention

When it happens

Trigger: Precompiled-query code generation encounters a type used in an intercepted operator that is a ref/out parameter type, an unsafe pointer type, a generic type parameter (T), or a ref struct (Span<T>, ReadOnlySpan<T>, etc.). GetTypeSymbol checks type.IsByRef || type.IsPointer || type.IsGenericParameter || type.IsByRefLike and throws.

Common situations: A query operator signature involves a ref struct such as Span<T> or a by-ref parameter. Capturing a generic type parameter that has no concrete symbol. Using unsafe/interop types in a query slated for precompilation. These types cannot appear in the generated interceptor's parameter list.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/b5322f1b49ab8bde. Report an issue: GitHub.