vitessio/vitess · error

err

Error message

err

What it means

This is an unrecoverable panic raised inside the VTGate planning stage while adding columns to an Aggregator operator. `expr.GetAliasedExpr()` fails when a select expression is not a plain aliased expression at this point of horizon expansion, indicating an internal planner invariant violation rather than an invalid user query. The original error is re-panicked so planning aborts instead of producing a wrong plan.

Source

Thrown at go/vt/vtgate/planbuilder/operators/horizon_expanding.go:272

			newExprs = append(newExprs, newExpr)
			aggr.SubQueryExpression = append(aggr.SubQueryExpression, subqs...)
		} else {
			newExprs = append(newExprs, expr)
		}
	}
	if len(aggr.SubQueryExpression) > 0 {
		aggr.setPushColumn(newExprs)
	}

	return aggr
}

func addAllColumnsToAggregator(ctx *plancontext.PlanningContext, a *Aggregator, qp *QueryProjection) {
outer:
	for colIdx, expr := range qp.SelectExprs {
		ae, err := expr.GetAliasedExpr()
		if err != nil {
			panic(err)
		}
		addedToCol := false
		for idx, groupBy := range a.Grouping {
			if ctx.SemTable.EqualsExprWithDeps(groupBy.Inner, ae.Expr) {
				if !addedToCol {
					a.Columns = append(a.Columns, ae)
					addedToCol = true
				}
				if groupBy.ColOffset < 0 {
					a.Grouping[idx].ColOffset = colIdx
				}
			}
		}
		if addedToCol {
			continue
		}
		for idx, aggr := range a.Aggregations {
			if ctx.SemTable.EqualsExprWithDeps(aggr.Original.Expr, ae.Expr) && aggr.ColOffset < 0 {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Capture the failing query and file a bug with the Vitess project — this panic indicates a planner bug, not user error
  2. Simplify the query: rewrite complex SELECT expressions so each is a plain column reference or explicitly aliased expression
  3. Try restructuring the aggregation (e.g. move expressions into a derived table and aggregate over it)
  4. Check the Vitess version and upgrade — such invariant panics are frequently fixed in newer releases

Example fix

// before (query that may trigger)
SELECT a+b, COUNT(*) FROM t GROUP BY a+b;
// after (pre-alias so planner sees a plain aliased expr)
SELECT (a+b) AS s, COUNT(*) FROM t GROUP BY s;
Defensive patterns

Strategy: validation

Validate before calling

// Run the query with ONLY_FULL_GROUP_BY against a plain MySQL first;
// only plain aliased expressions in the SELECT list of aggregated queries.
func hasPlainAliasedSelectExprs(sel *sqlparser.Select) bool {
  for _, e := range sel.SelectExprs {
    if _, ok := e.(*sqlparser.AliasedExpr); !ok { return false }
  }
  return true
}

Type guard

if ae, ok := expr.(sqlparser.SelectExpr); ok {
  if _, isAliased := ae.GetAliasedExpr(); isAliased == false { /* avoid path */ }
}

Try / catch

// In Vitess code paths that call planning, recover planner panics:
func safePlan(q string) (plan any, err error) {
  defer func() {
    if r := recover(); r != nil { err = fmt.Errorf("planning failed: %v", r) }
  }()
  return planQuery(q)
}

Prevention

When it happens

Trigger: A query containing an aggregation reaches addAllColumnsToAggregator (via createProjectionWithAggr) and one of the QueryProjection SelectExprs cannot be converted to an *sqlparser.AliasedExpr by GetAliasedExpr() — e.g. an unexpected expression shape survives earlier planning phases.

Common situations: Complex or unusual SELECT expressions combined with GROUP BY that the planner's earlier rewrite stages did not normalize; often hit during development of new SQL features or by fuzzer-generated queries rather than ordinary application SQL.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/8808dee2b73b1224. Report an issue: GitHub.