dotnet/efcore · error · NotSupportedException

Missing default arm for switch expression

Error message

Missing default arm for switch expression

What it means

In expression context a C# switch expression must be exhaustive and therefore requires a discard (_) arm. If switchNode.DefaultBody is null the translator cannot emit a valid switch expression, so it throws NotSupportedException. (In statement context a missing default is allowed, so this only fires for value-returning switches.)

Source

Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:2257

                    var result = translatedBody switch
                    {
                        BlockSyntax block => SingletonList<StatementSyntax>(block.WithStatements(block.Statements.Add(BreakStatement()))),
                        StatementSyntax s => List([s, BreakStatement()]),
                        ExpressionSyntax e => List(new StatementSyntax[] { ExpressionStatement(e), BreakStatement() }),

                        _ => throw new ArgumentOutOfRangeException()
                    };

                    return result;
                }
            }

            case ExpressionContext.Expression:
            case ExpressionContext.ExpressionLambda:
            {
                if (switchNode.DefaultBody is null)
                {
                    throw new NotSupportedException("Missing default arm for switch expression");
                }

                var parentLiftedState = _liftedState;
                _liftedState = parentLiftedState.CreateChild();

                // Translate all arms
                var arms = SeparatedList(
                    switchNode.Cases.SelectMany(
                            c => c.TestValues, (c, tv) => SwitchExpressionArm(
                                ConstantPattern(Translate<ExpressionSyntax>(tv)),
                                Translate<ExpressionSyntax>(c.Body)))
                        .Append(SwitchExpressionArm(DiscardPattern(), Translate<ExpressionSyntax>(switchNode.DefaultBody))));

                // LINQ SwitchExpression supports non-literal labels, which C# does not support. This rewrites the switch as a series of
                // nested ConditionalExpressions.
                if (arms.Any(a => a.Pattern is ConstantPatternSyntax cp && !_constantDetector.IsConstant(cp.Expression)))
                {
                    _liftedState = parentLiftedState;

View on GitHub (pinned to dbf9771522)

Solutions

  1. Provide a default body: Expression.Switch(value, defaultBody, cases).
  2. Use the switch in statement context (where a default is optional) instead of as a value.
  3. Rewrite as nested Conditional (Expression.Condition) expressions which can omit a final fallback.

Example fix

// before
var sw = Expression.Switch(value, new[] { case1, case2 }); // no default body -> throws as value
// after
var sw = Expression.Switch(value, Expression.Constant(0), new[] { case1, case2 });
Defensive patterns

Strategy: validation

Validate before calling

// If a switch is used as a value, ensure it has a default body
protected override Expression VisitSwitch(SwitchExpression s) {
    if (s.DefaultBody is null && s.Type != typeof(void)) Found = true;
    return s;
}

Prevention

When it happens

Trigger: A SwitchExpression used as a value (e.g. inside a Select projection, in Expression/ExpressionLambda context) that has no default body.

Common situations: Building Expression.Switch(value, cases) without the default-body argument and then using the result as a value in a compiled query.

Related errors


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