dotnet/efcore · error · InvalidOperationException
Encountered {SyntaxKind.IsExpression} with non-constant type
Error message
Encountered {SyntaxKind.IsExpression} with non-constant type right argument: {right} What it means
In the `SyntaxKind.IsExpression` arm of `VisitBinaryExpression`, the translator requires the right operand to be a `ConstantExpression` whose `Value` is a `Type` (i.e. `x is SomeType`). If the right side is not a constant type it throws `InvalidOperationException`, because richer pattern-matching forms (`is int y`, `is { Length: > 0 }`) cannot be represented.
Source
Thrown at src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs:315
SyntaxKind.ExclusiveOrExpression when left.Type.IsEnum || right.Type.IsEnum
=> Convert(
ExclusiveOr(Convert(left, left.Type.GetEnumUnderlyingType()), Convert(right, right.Type.GetEnumUnderlyingType())),
left.Type),
SyntaxKind.BitwiseOrExpression => Or(left, right),
SyntaxKind.BitwiseAndExpression => And(left, right),
SyntaxKind.ExclusiveOrExpression => ExclusiveOr(left, right),
SyntaxKind.EqualsExpression => Equal(left, right),
SyntaxKind.NotEqualsExpression => NotEqual(left, right),
SyntaxKind.LessThanExpression => LessThan(left, right),
SyntaxKind.LessThanOrEqualExpression => LessThanOrEqual(left, right),
SyntaxKind.GreaterThanExpression => GreaterThan(left, right),
SyntaxKind.GreaterThanOrEqualExpression => GreaterThanOrEqual(left, right),
SyntaxKind.IsExpression => TypeIs(
left, right is ConstantExpression { Value: Type type }
? type
: throw new InvalidOperationException(
$"Encountered {SyntaxKind.IsExpression} with non-constant type right argument: {right}")),
SyntaxKind.AsExpression => TypeAs(
left, right is ConstantExpression { Value: Type type }
? type
: throw new InvalidOperationException(
$"Encountered {SyntaxKind.AsExpression} with non-constant type right argument: {right}")),
SyntaxKind.CoalesceExpression => Coalesce(left, right),
_ => throw new ArgumentOutOfRangeException($"BinaryExpressionSyntax with {binary.Kind()}")
};
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>View on GitHub (pinned to dbf9771522)
Solutions
- Use a plain type test (`x is SomeType`) and follow with explicit casts/member access.
- Move the pattern-matching logic out of the query and apply it to materialized results.
Example fix
// before var q = ctx.Items.Where(i => (i.Data as object) is int n && n > 0); // after var q = ctx.Items.Where(i => i.Data is int).Select(i => (int)i.Data).Where(n => n > 0);
Defensive patterns
Strategy: validation
Validate before calling
// Scan for non-trivial 'is' patterns the translator cannot handle.
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
bool unsupportedIs = node.DescendantNodes().OfType<BinaryExpressionSyntax>()
.Any(b => b.IsKind(SyntaxKind.IsExpression)
&& !(b.Right is PredefinedTypeSyntax || b.Right is IdentifierNameSyntax || b.Right is QualifiedNameSyntax));
if (unsupportedIs)
throw new NotSupportedException("Only plain type tests (`x is T`) are supported in precompiled queries.");
translator.Translate(node, semanticModel); Try / catch
try { translator.Translate(node, semanticModel); }
catch (InvalidOperationException ex) when (ex.Message.Contains("IsExpression") && ex.Message.Contains("non-constant type"))
{ /* rewrite the pattern as a plain type test + casts */ } Prevention
- Use plain type tests (`x is T`) inside queries; avoid `is T v` and recursive patterns there.
- Apply complex pattern matching after materialization.
When it happens
Trigger: A precompiled query using C# pattern matching on the left of `is` with anything other than a bare type, e.g. `obj is int n`, `o is string { Length: > 0 }`, or a switch-expression-style `is` pattern.
Common situations: Writing modern C# patterns inside a query lambda; the compiler accepts them but the translator's expression-tree model does not.
Related errors
- Encountered {SyntaxKind.AsExpression} with non-constant type
- Argument with ref/out: {argument}
- ArrayCreation: multi-dimensional array: {arrayCreation}
- BinaryExpressionSyntax with {binary.Kind()}
- ElementAccessExpressionSyntax over non-array
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/fa153238c97c8d55.
Report an issue: GitHub.