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
- Remove or rewrite the statement — DML against information_schema is not allowed
- If the intent was metadata inspection, use SELECT instead of UPDATE/INSERT/DELETE
- Adjust application/tooling configuration to exclude system schema tables from DML generation
- 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
- Never issue DML against information_schema/performance_schema through Vitess
- Exclude system schemas from ORM/migration tooling DML generation
- Use ALTER TABLE on the base table to change metadata like comments
- Treat VT12001 as a design signal: such operations are unsupported by design, not a transient failure
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.