{"record":{"id":"f5a98864c9e3a38c","repo":"vitessio/vitess","slug":"vt12001-f5a988","errorCode":"VT12001","errorMessage":"VT12001: unsupported: in scatter query: complex aggregate expression","messagePattern":"VT12001: unsupported: in scatter query: complex aggregate expression","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/planbuilder/operators/queryprojection.go","lineNumber":442,"sourceCode":"\t\tif !ctx.ContainsAggr(selectExpr.Col) {\n\t\t\tgetExpr, err := selectExpr.GetExpr()\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\n\t\t\tif ctx.ContainsWindowFunc(selectExpr.Col) {\n\t\t\t\tsqlparser.CopyOnRewrite(aliasedExpr.Expr, qp.extractAggr(ctx, aliasedExpr, addAggr, makeComplex), nil, nil)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif !qp.isExprInGroupByExprs(ctx, getExpr) {\n\t\t\t\taggr := createNonGroupingAggr(aliasedExpr)\n\t\t\t\tout = append(out, aggr)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif !ctx.IsAggr(aliasedExpr.Expr) && !allowComplexExpression {\n\t\t\tpanic(vterrors.VT12001(\"in scatter query: complex aggregate expression\"))\n\t\t}\n\n\t\tsqlparser.CopyOnRewrite(aliasedExpr.Expr, qp.extractAggr(ctx, aliasedExpr, addAggr, makeComplex), nil, nil)\n\t}\n\treturn\n}\n\nfunc (qp *QueryProjection) extractAggr(\n\tctx *plancontext.PlanningContext,\n\taliasedExpr *sqlparser.AliasedExpr,\n\taddAggr func(a Aggr),\n\tmakeComplex func(),\n) func(node sqlparser.SQLNode, parent sqlparser.SQLNode) bool {\n\treturn func(node, parent sqlparser.SQLNode) bool {\n\t\tex, isExpr := node.(sqlparser.Expr)\n\t\tif !isExpr {\n\t\t\treturn true\n\t\t}","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/planbuilder/operators/queryprojection.go#L424-L460","documentation":"VT12001 is raised when AggregationExpressions encounters an aggregate expression that is neither a simple aggregate nor permitted as a complex expression, in a scatter query. Scatter queries aggregate results across shards, so each output column must be a directly pushable aggregate; arbitrary complex expressions over aggregates cannot be computed correctly from partial per-shard results.","triggerScenarios":"createProjectionWithAggr calls AggregationExpressions with allowComplexExpression=false for a scatter-route query whose SELECT contains a complex expression mixing aggregates with other expressions (e.g. `SUM(x)/COUNT(y)` composed with extra terms the planner can't push down).","commonSituations":"Aggregates over sharded tables without a usable sharding-key predicate (forcing scatter), combined with complex expressions like arithmetic on aggregates or nested functions, e.g. `SELECT SUM(a) - SUM(b) FROM t` on a scatter.","solutions":["Rewrite the query so each aggregate is a simple top-level function, e.g. `SELECT SUM(a), SUM(b) FROM t` and compute `SUM(a)-SUM(b)` in the application.","Add a predicate on the sharding key (e.g. `WHERE sharding_key = ?`) so the query routes to a single shard instead of scattering.","Restructure the VSchema/sharding or use an unsharded keyspace if the aggregate pattern is common."],"exampleFix":"// before\nSELECT SUM(price) / COUNT(*) AS avg_price FROM orders;\n// after\nSELECT SUM(price) AS total, COUNT(*) AS cnt FROM orders; // divide client-side","handlingStrategy":"try-catch","validationCode":"// Reject complex arithmetic over aggregates for scatter routes before sending\nif isScatterRoute(query) && containsNestedAggregateExpr(query) {\n    return errors.New(\"rewrite query: scatter queries only support simple top-level aggregates\")\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"VT12001\") && strings.Contains(err.Error(), \"scatter\") {\n    // fall back to splitting aggregates client-side or route with sharding key\n}","preventionTips":["Keep aggregate SELECTs to simple top-level aggregate functions","Add sharding-key predicates to avoid scatter routes","Compute post-aggregate arithmetic in the application"],"tags":["vtgate","aggregation","scatter-query","unsupported"],"backgroundTag":"unsupported-scatter-aggregate","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}