vitessio/vitess · error

VT13001

VT13001

Error message

Unknown SelectStatement type - %T

What it means

VT13001 panic in isMergeable: the planner's switch over sqlparser.SelectStatement types has a default case, meaning an unhandled SelectStatement AST node type was encountered while deciding whether a statement is mergeable. This is an internal completeness check — the parser should never produce a statement type the planner does not know.

Source

Thrown at go/vt/vtgate/planbuilder/operators/subquery_planning.go:72

			// TODO: we could also support the case where all the columns of a multi-column vindex are used in the grouping
			return slices.ContainsFunc(node.GroupBy.Exprs, validVindex)
		}

		// if we have grouping, we have already checked that it's safe, and don't need to check for aggregations
		// but if we don't have groupings, we need to check if there are aggregations that will mess with us
		if ctx.ContainsAggr(node.SelectExprs) {
			return false
		}

		if ctx.ContainsAggr(node.Having) {
			return false
		}

		return true
	case *sqlparser.Union:
		return isMergeable(ctx, node.Left, op) && isMergeable(ctx, node.Right, op)
	default:
		panic(vterrors.VT13001(fmt.Sprintf("Unknown SelectStatement type - %T", node)))
	}
}

func settleSubqueries(ctx *plancontext.PlanningContext, op Operator) Operator {
	visit := func(op Operator, lhsTables semantics.TableSet, isRoot bool) (Operator, *ApplyResult) {
		switch op := op.(type) {
		case *SubQueryContainer:
			outer := op.Outer
			for _, subq := range op.Inner {
				subq.Outer = subq.settle(ctx, outer)
				outer = subq
			}
			return outer, Rewrote("extracted subqueries from subquery container")
		case *Projection:
			ap, err := op.GetAliasedProjections()
			if err != nil {
				panic(err)
			}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. File a bug with the SQL statement and stack trace at the Vitess repository
  2. Upgrade to the latest Vitess release where newer statement types may be handled
  3. Rewrite the query using more standard SELECT/UNION syntax
  4. As a workaround, run the statement directly against MySQL bypassing vtgate planning if applicable
Defensive patterns

Strategy: fallback

Try / catch

err := doQuery(q)
if err != nil && strings.Contains(err.Error(), "VT13001") && strings.Contains(err.Error(), "Unknown SelectStatement type") {
    // report bug; try a simplified/standard rewrite of the statement
    return doQuery(simplifyStatement(q))
}

Prevention

When it happens

Trigger: isMergeable (via IsMergeable or recursion on Union operands) receives a SelectStatement implementation not covered by the switch cases (Select, Union, etc.), typically after a new AST node type is added to the parser without planner support.

Common situations: Seen in Vitess development when new SQL syntax is added to the parser; extremely rare for users, but could be reported when running newly parsed exotic statements (e.g. new table expression types) through the planner.

Related errors


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