vitessio/vitess · error · VitessError
VT09004
VT09004
Error message
VT09004: INSERT should contain column list or the table should have authoritative columns in vschema
What it means
VT09004 is raised by createInsertOperator in go/vt/vtgate/planbuilder/operators/insert.go:382 when an INSERT omits its column list AND the target table's vschema entry is not marked ColumnListAuthoritative. Without a column list or an authoritative column list, Vitess cannot map each value to a column and cannot populate the insert plan.
Source
Thrown at go/vt/vtgate/planbuilder/operators/insert.go:382
}
insOp := &Insert{
VTable: vTbl,
AST: insStmt,
}
route := &Route{
unaryOperator: newUnaryOp(insOp),
Routing: routing,
}
// Table column list is nil then add all the columns
// If the column list is empty then add only the auto-inc column and
// this happens on calling modifyForAutoinc
if insStmt.Columns == nil && valuesProvided(insStmt.Rows) {
if vTbl.ColumnListAuthoritative {
insStmt = populateInsertColumnlist(insStmt, vTbl)
} else {
panic(vterrors.VT09004())
}
}
// modify column list or values for autoincrement column.
autoIncGen := modifyForAutoinc(ctx, insStmt, vTbl)
insOp.AutoIncrement = autoIncGen
// set insert ignore.
insOp.Ignore = bool(insStmt.Ignore) || insStmt.OnDup != nil
insOp.ColVindexes = getColVindexes(insOp)
switch rows := insStmt.Rows.(type) {
case sqlparser.Values:
op = route
route.Source = insertRowsPlan(ctx, insOp, insStmt, rows)
case sqlparser.TableStatement:
op = insertSelectPlan(ctx, insOp, route, insStmt, rows)
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Rewrite the INSERT to include an explicit column list: INSERT INTO t (col1, col2) VALUES (...)
- Set `column_list_authoritative: true` on the table's vschema definition if the column list is complete and stable
- Resync the vschema with the physical table schema before enabling authoritative columns
Example fix
// before INSERT INTO users VALUES (1, 'alice'); // after INSERT INTO users (id, name) VALUES (1, 'alice');
Defensive patterns
Strategy: validation
Validate before calling
// Require an explicit column list for inserts into Vitess tables
const insertRe = /^INSERT\s+INTO\s+[`\w.]+\s*VALUES/i;
if (insertRe.test(sql)) {
throw new Error('INSERT must include an explicit column list');
} Type guard
function hasColumnList(insertAst) {
return Array.isArray(insertAst.columns) && insertAst.columns.length > 0;
} Try / catch
try {
await vtgate.execute(sql, args);
} catch (e) {
if (String(e).includes('VT09004')) {
throw new Error('Add a column list to the INSERT or set column_list_authoritative in the vschema: ' + e.message);
}
throw e;
} Prevention
- Always write INSERTs with explicit column lists
- Enable column_list_authoritative in the vschema when the physical schema is stable
- Add a lint rule forbidding bare `INSERT INTO t VALUES (...)` in application SQL
When it happens
Trigger: Executing `INSERT INTO t VALUES (...)` (no column list, rows provided) where the vschema table definition for t lacks `column_list_authoritative: true`.
Common situations: Legacy SQL written without explicit column lists being pointed at Vitess; vschema (JSON) files migrated manually without setting column_list_authoritative; tables whose physical schema can change so authoritative lists were intentionally avoided.
Related errors
- VT03014
- value must be either a float64 (interpreted as seconds) or a
- flagutil: NewOptionalFlag requires a non-nil parse function
- flagutil: OptionalFlagValue has no parse function; use a con
- one or two tables must be specified
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/8a03d736fdbec1b8.
Report an issue: GitHub.