vitessio/vitess · error

vtexplain: unsupported statement type +%v

Error message

vtexplain: unsupported statement type +%v

What it means

In handleSelect, vtexplain accepts only *sqlparser.Select, *sqlparser.ParenSelect and *sqlparser.Union as the statement to analyze; any other AST node type falls into the default branch and is rejected with this message including the reflect type. It is an internal guard for the select-explaining path.

Source

Thrown at go/vt/vtexplain/vtexplain_vttablet.go:628

	// Parse the select statement to figure out the table and columns
	// that were referenced so that the synthetic response has the
	// expected field names and types.
	stmt, err := t.vte.env.Parser().Parse(query)
	if err != nil {
		return nil, err
	}

	var selStmt *sqlparser.Select
	switch stmt := stmt.(type) {
	case *sqlparser.Select:
		selStmt = stmt
	case *sqlparser.Union:
		selStmt, err = sqlparser.GetFirstSelect(stmt)
		if err != nil {
			return nil, err
		}
	default:
		return nil, fmt.Errorf("vtexplain: unsupported statement type +%v", reflect.TypeOf(stmt))
	}

	// Gen4 supports more complex queries so we now need to
	// handle multiple FROM clauses
	tables := make([]*sqlparser.AliasedTableExpr, 0, len(selStmt.From))
	for _, from := range selStmt.From {
		tables = append(tables, getTables(from)...)
	}

	tableColumnMap := map[sqlparser.IdentifierCS]map[string]querypb.Type{}
	for _, table := range tables {
		if table == nil {
			continue
		}

		tableName := sqlparser.String(sqlparser.GetTableName(table.Expr))
		columns, exists := t.vte.getGlobalTabletEnv().tableColumns[tableName]
		if !exists && tableName != "" {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Ensure only SELECT/UNION statements reach handleSelect.
  2. Update vtexplain to handle the new statement AST type in the switch.
  3. Use HandleQuery which routes by statement type instead of calling handleSelect directly.
Defensive patterns

Strategy: validation

Validate before calling

switch stmt.(type) {
case *sqlparser.Select, *sqlparser.ParenSelect, *sqlparser.Union:
    // safe to pass to handleSelect
default:
    return fmt.Errorf("not a select: %T", stmt)
}

Type guard

func isExplainableSelect(stmt sqlparser.Statement) bool {
    switch stmt.(type) {
    case *sqlparser.Select, *sqlparser.ParenSelect, *sqlparser.Union:
        return true
    }
    return false
}

Try / catch

res, err := tablet.handleSelect(query)
if err != nil {
    if strings.Contains(err.Error(), "unsupported statement type") {
        // route to a different handler or skip
    }
}

Prevention

When it happens

Trigger: A statement typed as select-like but whose AST is none of Select/ParenSelect/Union (e.g. a SHOW or other statement that reached handleSelect), producing reflect type output in the error.

Common situations: Routing bugs in tools built on vtexplain; newer parser statement kinds not yet handled; passing arbitrary statements into the explain-select path programmatically.

Related errors


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