{"record":{"id":"11404bc1d554b0fb","repo":"dotnet/efcore","slug":"unhandledexpressioninvisitor","errorCode":"UnhandledExpressionInVisitor","errorMessage":"Unhandled expression '{expression}' of type '{expressionType}' encountered in '{visitor}'.","messagePattern":"Unhandled expression '(.+?)' of type '(.+?)' encountered in '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/QuerySqlGenerator.cs","lineNumber":157,"sourceCode":"            RightJoinExpression e => VisitRightJoin(e),\n            FullJoinExpression e => VisitFullJoin(e),\n            RowNumberExpression e => VisitRowNumber(e),\n            RowValueExpression e => VisitRowValue(e),\n            ScalarSubqueryExpression e => VisitScalarSubquery(e),\n            SelectExpression e => VisitSelect(e),\n            SqlBinaryExpression e => VisitSqlBinary(e),\n            SqlConstantExpression e => VisitSqlConstant(e),\n            SqlFragmentExpression e => VisitSqlFragment(e),\n            SqlFunctionExpression e => VisitSqlFunction(e),\n            SqlParameterExpression e => VisitSqlParameter(e),\n            SqlUnaryExpression e => VisitSqlUnary(e),\n            TableExpression e => VisitTable(e),\n            UnionExpression e => VisitUnion(e),\n            UpdateExpression e => VisitUpdate(e),\n            JsonScalarExpression e => VisitJsonScalar(e),\n            ValuesExpression e => VisitValues(e),\n\n            _ => throw new InvalidOperationException(\n                RelationalStrings.UnhandledExpressionInVisitor(expression, expression.GetType(), nameof(QuerySqlGenerator))),\n        };\n\n    /// <summary>\n    ///     Generates SQL for an arbitrary fragment.\n    /// </summary>\n    /// <param name=\"sqlFragmentExpression\">The <see cref=\"SqlFragmentExpression\" /> for which to generate SQL.</param>\n    protected virtual Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression)\n    {\n        _relationalCommandBuilder.Append(sqlFragmentExpression.Sql);\n\n        return sqlFragmentExpression;\n    }\n\n    private static bool TryUnwrapBareSetOperation(SelectExpression selectExpression, [NotNullWhen(true)] out SetOperationBase? setOperation)\n    {\n        if (selectExpression is\n            {","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/QuerySqlGenerator.cs#L139-L175","documentation":"Thrown by QuerySqlGenerator.Visit (QuerySqlGenerator.cs:157) when the expression-type switch hits the default case: the SQL generator received a SqlExpression/SelectExpression subtype it has no Visit method for. The relational SQL generator enumerates every supported expression kind; anything else is untranslatable to SQL, so EF throws rather than emit malformed SQL. This usually indicates a provider bug or an unsupported expression leaking into SQL generation.","triggerScenarios":"A custom or provider-specific SqlExpression reaches the base QuerySqlGenerator without the provider having overridden the appropriate Visit method. Triggered by providers that introduce new expression types but don't teach the SQL generator to emit them, or by query shapes that surface an unexpected node.","commonSituations":"Database provider version mismatch (provider emits a node the base generator doesn't know); third-party EF extensions introducing custom SQL expressions; EF Core upgrade where a new expression type was added but the provider wasn't updated; bugs producing unexpected expression trees.","solutions":["If you are a provider author, override the correct Visit method in your QuerySqlGenerator for the new expression type.","Ensure your EF Core provider version matches (is compatible with) your EF Core runtime version.","Update the provider to the latest release; report the unhandled expression type to the provider/EF team.","Simplify the query to avoid the construct that produces the unsupported node, and check EF logs for the expression type in the error."],"exampleFix":"// before (provider) - a custom SqlExpression reaches the base generator unhandled\npublic class MyWindowExpression : SqlExpression { ... }\n// QuerySqlGenerator.Visit hits default -> UnhandledExpressionInVisitor\n\n// after - override the visitor in your provider's QuerySqlGenerator\nprotected override Expression VisitExtension(Expression e) {\n    return e is MyWindowExpression win ? VisitMyWindow(win) : base.VisitExtension(e);\n}\nprivate Expression VisitMyWindow(MyWindowExpression e) { /* emit SQL */ return e; }","handlingStrategy":"validation","validationCode":"// Provider: ensure your QuerySqlGenerator handles every expression type your translation emits.\nprotected override Expression VisitExtension(Expression e)\n    => e is MyCustomSqlExpression c ? VisitCustom(c) : base.VisitExtension(e);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep your EF Core provider version in sync with the EF Core runtime version.","Provider authors: override the relevant Visit method for every custom SqlExpression.","Simplify queries that surface unsupported expression nodes; report them to the provider.","Check EF logs for the expression type named in the error."],"tags":["ef-core","sql-generation","provider","expression-tree","query"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}