vitessio/vitess · error

VT12001

VT12001

Error message

update information schema tables

What it means

VT12001 is Vitess's 'feature not supported online' error. During INSERT/UPDATE planning, createQueryTableForDML checks the target table and raises VT12001 when the target is an information_schema table, because DML against information_schema cannot be planned or executed by Vitess. Unlike the other panics, this is an intentional, user-facing error for unsupported DML targets.

Source

Thrown at go/vt/vtgate/planbuilder/operators/ast_to_op.go:445

	whereClause *sqlparser.Where,
) (semantics.TableInfo, *QueryTable) {
	alTbl, ok := tableExpr.(*sqlparser.AliasedTableExpr)
	if !ok {
		panic(vterrors.VT13001("expected AliasedTableExpr"))
	}
	tblName, ok := alTbl.Expr.(sqlparser.TableName)
	if !ok {
		panic(vterrors.VT13001("expected TableName"))
	}

	tableID := ctx.SemTable.TableSetFor(alTbl)
	tableInfo, err := ctx.SemTable.TableInfoFor(tableID)
	if err != nil {
		panic(err)
	}

	if tableInfo.IsInfSchema() {
		panic(vterrors.VT12001("update information schema tables"))
	}

	var predicates []sqlparser.Expr
	if whereClause != nil {
		predicates = sqlparser.SplitAndExpression(nil, whereClause.Expr)
	}
	qt := &QueryTable{
		ID:         tableID,
		Alias:      alTbl,
		Table:      tblName,
		Predicates: predicates,
	}
	return tableInfo, qt
}

func addColumnEquality(ctx *plancontext.PlanningContext, expr sqlparser.Expr) {
	switch expr := expr.(type) {
	case *sqlparser.ComparisonExpr:

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Remove or rewrite the statement — DML against information_schema is not allowed
  2. If the intent was metadata inspection, use SELECT instead of UPDATE/INSERT/DELETE
  3. Adjust application/tooling configuration to exclude system schema tables from DML generation
  4. In MySQL directly (not through Vitess), such DML would require SUPER and is generally pointless — redesign the workflow

Example fix

// before
UPDATE information_schema.tables SET table_comment = 'x' WHERE table_name = 't';
// after
-- alter the actual table instead
ALTER TABLE `t` COMMENT = 'x';
Defensive patterns

Strategy: try-catch

Validate before calling

// Inspect the query target before sending DML
func isSystemSchemaDML(q string) bool {
	parsed, err := sqlparser.Parse(q)
	if err != nil {
		return false
	}
	tbls := sqlparser.GetTablesets(parsed)
	for _, t := range tbls {
		if strings.EqualFold(t.Qualifier.String(), "information_schema") ||
			strings.EqualFold(t.Qualifier.String(), "performance_schema") ||
			strings.EqualFold(t.Qualifier.String(), "mysql") {
			return true
		}
	}
	return false
}

Type guard

func targetsInfoSchema(stmt sqlparser.Statement) bool {
	tbl, ok := stmt.(*sqlparser.Update)
	if !ok { return false }
	n, err := sqlparser.TableFromStatement(tbl.TableExprs)
	if err != nil { return false }
	return strings.EqualFold(n.Qualifier.String(), "information_schema")
}

Try / catch

_, err := vtgate.Execute(ctx, session, "UPDATE information_schema.tables SET ...", nil)
if err != nil {
	var ec *vterrors.ErrorCode
	if errors.As(err, &ec) && ec.Code() == vtrpcpb.Code_NOT_SUPPORTED /* VT12001 */ {
		// route DML to the real base table instead
	}
}

Prevention

When it happens

Trigger: Running an UPDATE (via createOperatorFromInsert/DML planning) whose target table resolves to an information_schema table through the semantic table analysis — e.g., `UPDATE information_schema.tables SET ...`.

Common situations: Migration scripts or ORM tooling that issues DML against information_schema tables; applications assuming MySQL semantics where such statements may parse but have no effect; tools auto-generating SQL from metadata queries.

Related errors


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