{"record":{"id":"e966b496ab0e427d","repo":"dotnet/efcore","slug":"this-node-should-be-handled-by-provider-specific-s","errorCode":null,"errorMessage":"This node should be handled by provider-specific SQL generator.","messagePattern":"This node should be handled by provider-specific SQL generator\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/QuerySqlGenerator.cs","lineNumber":1673,"sourceCode":"\n            for (var i = 1; i < rowValues.Count; i++)\n            {\n                if (i > 1)\n                {\n                    _relationalCommandBuilder.Append(\", \");\n                }\n\n                Visit(valuesExpression.RowValues[i]);\n            }\n        }\n    }\n\n    /// <summary>\n    ///     Generates SQL for a JSON scalar lookup expression.\n    /// </summary>\n    /// <param name=\"jsonScalarExpression\">The <see cref=\"JsonScalarExpression\" /> for which to generate SQL.</param>\n    protected virtual Expression VisitJsonScalar(JsonScalarExpression jsonScalarExpression)\n        => throw new InvalidOperationException(\n            RelationalStrings.JsonNodeMustBeHandledByProviderSpecificVisitor);\n\n    /// <summary>\n    ///     Returns a bool value indicating if the inner SQL expression required to be put inside parenthesis when generating SQL for outer\n    ///     SQL expression.\n    /// </summary>\n    /// <param name=\"outerExpression\">The outer expression which provides context in which SQL is being generated.</param>\n    /// <param name=\"innerExpression\">The inner expression which may need to be put inside parenthesis.</param>\n    /// <returns>A bool value indicating that parenthesis is required or not. </returns>\n    protected virtual bool RequiresParentheses(SqlExpression outerExpression, SqlExpression innerExpression)\n    {\n        int outerPrecedence, innerPrecedence;\n\n        // Convert is rendered as a function (CAST()) and not as an operator, so we never need to add parentheses around the inner\n        if (outerExpression is SqlUnaryExpression { OperatorType: ExpressionType.Convert })\n        {\n            return false;\n        }","sourceCodeStart":1655,"sourceCodeEnd":1691,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/QuerySqlGenerator.cs#L1655-L1691","documentation":"The base relational QuerySqlGenerator.VisitJsonScalar throws by design: JsonScalarExpression nodes must be rewritten/expanded by the provider-specific SQL generator (or eliminated earlier in the pipeline) before reaching this default visitor. Seeing it means a JSON path expression survived into SQL generation unhandled.","triggerScenarios":"Querying a JSON-mapped owned property in a way that yields a JsonScalarExpression at SQL-generation time when the provider does not override VisitJsonScalar or did not expand it. Typically with providers/versions that do not support JSON columns (e.g. SQLite without the JSON-owning bits, older SQL Server provider on JSON-mapped entities), or when an internal rewrite pass is skipped.","commonSituations":"Mapping an owned entity type to JSON (.ToJson()) and then projecting/filtering on its scalar properties under a provider that lacks JSON support; upgrading EF Core without upgrading the provider; using a community provider that has not implemented the JSON visitor.","solutions":["Use a provider that supports JSON columns for your database (e.g. Microsoft.EntityFrameworkCore.SqlServer with JSON mapping support, Npgsql for PostgreSQL).","Ensure the EF Core relational package and provider package versions match.","If JSON mapping is not required, remap the owned type to a separate column/table or as a complex type.","File an issue against the provider if it claims JSON support but leaves JsonScalarExpression unhandled."],"exampleFix":"// before (provider lacks JSON support)\nmodelBuilder.Entity<Order>()\n    .OwnsOne(o => o.Address, a => a.ToJson());\nvar city = await db.Orders.Select(o => o.Address.City).ToListAsync();\n// after (map as columns instead)\nmodelBuilder.Entity<Order>()\n    .OwnsOne(o => o.Address);  // table columns\nvar city = await db.Orders.Select(o => o.Address.City).ToListAsync();","handlingStrategy":"validation","validationCode":"// Verify the provider advertises JSON support before mapping to JSON.\nvar providerName = db.Database.ProviderName;\nvar supportsJson = providerName is\n    \"Microsoft.EntityFrameworkCore.SqlServer\"      // recent versions w/ JSON\n    or \"Npgsql.EntityFrameworkCore.PostgreSQL\";    // jsonb\nif (!supportsJson)\n    throw new InvalidOperationException($\"Provider {providerName} cannot translate JSON-mapped owned entities.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Match EF Core relational and provider package versions.","Map owned types to columns/tables unless you specifically need JSON and your provider supports it.","File a provider issue if JSON support is claimed but VisitJsonScalar is unhandled."],"tags":["efcore","json","provider-bug","owned-types","query-translation"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}