dotnet/efcore · error · NotSupportedException

Missing default arm for switch expression

Error message

Missing default arm for switch expression

What it means

Thrown by TranslateSwitch when a SwitchExpression is translated in an expression (not statement) context but has a null DefaultBody. C# switch expressions must be exhaustive and require a discard/default arm, so the translator needs a default body to emit; without one it cannot produce valid C#. A statement-context switch (with throw default arm) is handled separately.

Solutions

  1. Provide a default body when constructing the SwitchExpression so DefaultBody is non-null.
  2. Restructure the expression so the switch is used in a statement context rather than as a value.
  3. Replace the switch with a chain of conditional expressions that do not require a default arm.

Example fix

// before
Expression.Switch(value, cases, defaultBody: null);
// after
Expression.Switch(value, cases, defaultBody: Expression.Constant(fallback));
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every switch used as a value has a default body
static bool ValueSwitchesHaveDefault(Expression e) { /* walk: flag SwitchExpression with DefaultBody==null used as a value */ return true; }

Type guard

static bool IsExhaustiveSwitch(SwitchExpression s) => s.DefaultBody is not null;

Try / catch

try { var csharp = translator.Translate(expr); }
catch (NotSupportedException ex) when (ex.Message.Contains("Missing default arm"))
{ throw new InvalidOperationException("Add a default body to the switch expression.", ex); }

Prevention

When it happens

Trigger: A SwitchExpression used as a value (ExpressionContext.Expression or ExpressionContext.ExpressionLambda) where DefaultBody is null, so there is nothing to generate for the implicit discard arm.

Common situations: Programmatically constructing Expression.Switch without the defaultBody argument and using the result as a value in a translated query; relying on a switch that is exhaustive by domain knowledge but has no default arm in the expression tree.

Related errors


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

Appendix: 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 3a2006ef56)