vitessio/vitess · error

no columns available

Error message

no columns available

What it means

ValuesStatement.GetColumnCount() returns the width of the first row of a VALUES statement; with zero rows there is no row to measure, so it panics. The library has no defined column count for an empty VALUES clause and openly notes (TODO) that panicking is a stopgap.

Source

Thrown at go/vt/sqlparser/ast_funcs.go:3193

}

func (node *ValuesStatement) GetLimit() *Limit {
	return node.Limit
}

func (node *ValuesStatement) AddOrder(order *Order) {
	node.Order = append(node.Order, order)
}

func (node *ValuesStatement) SetLimit(limit *Limit) {
	node.Limit = limit
}

func (node *ValuesStatement) GetColumnCount() int {
	if len(node.Rows) > 0 {
		return len(node.Rows[0])
	}
	panic("no columns available") // TODO: we need a better solution than a panic
}

func (node *ValuesStatement) GetColumns() []SelectExpr {
	columnCount := node.GetColumnCount()
	sel := make([]SelectExpr, 0, columnCount)
	for i := range columnCount {
		sel = append(sel, &AliasedExpr{Expr: NewColName(fmt.Sprintf("column_%d", i))})
	}
	_ = sel
	panic("no columns available") // TODO: we need a better solution than a panic
}

func (node *ValuesStatement) SetComments(comments Comments) {}

func (node *ValuesStatement) GetParsedComments() *ParsedComments { return nil }

func NewFuncExpr(name string, exprs ...Expr) *FuncExpr {
	return &FuncExpr{

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Guard the call: check len(node.Rows) > 0 before calling GetColumnCount() on a ValuesStatement
  2. Skip VALUES statements without rows in your statement-walking code
  3. Fix the upstream parse/rewrite step that produced an empty VALUES node
  4. Contribute a fix upstream returning 0 or an error instead of panicking (the TODO acknowledges this)

Example fix

// before
count := stmt.(*sqlparser.ValuesStatement).GetColumnCount() // panics if no rows
// after
vs, ok := stmt.(*sqlparser.ValuesStatement)
if !ok || len(vs.Rows) == 0 {
    return 0, errors.New("values statement has no rows")
}
count := len(vs.Rows[0])
Defensive patterns

Strategy: validation

Validate before calling

func valuesColumnCount(vs *sqlparser.ValuesStatement) (int, error) {
    if vs == nil || len(vs.Rows) == 0 {
        return 0, errors.New("values statement has no rows")
    }
    return len(vs.Rows[0]), nil
}

Try / catch

func getColumnCountSafe(vs *sqlparser.ValuesStatement) (n int, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("GetColumnCount panicked: %v", r)
        }
    }()
    return vs.GetColumnCount(), nil
}

Prevention

When it happens

Trigger: Calling GetColumnCount() on a *ValuesStatement whose Rows slice is empty, e.g. a `VALUES ()`-style node or one produced by a failed/incomplete parse or hand-built AST.

Common situations: Analyses or rewriters that enumerate statements and call the Statement column-count interface on a degenerate VALUES node; fuzzed or malformed SQL reaching the analyzer; AST edits that removed all rows.

Related errors


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