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
- Provide a default body when constructing the SwitchExpression so DefaultBody is non-null.
- Restructure the expression so the switch is used in a statement context rather than as a value.
- 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
- Always pass a defaultBody to Expression.Switch.
- Prefer statement-context switches when a default is genuinely absent.
- Replace switches with conditional expressions when feasible.
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
- Switch with non-null comparison method
- Encountered non-quotable expression of type
- Unary node with non-null method
- Unnamed captured variable
- Unsupported LINQ unary node
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)