vitessio/vitess · error
could not determine CREATE TABLE statement from table schema
Error message
could not determine CREATE TABLE statement from table schema %q
What it means
During VReplication's copy phase, deferred secondary keys must be re-added after the bulk copy. To find which indexes exist, the table's SHOW CREATE TABLE output is fetched and parsed; this error is thrown when the parsed statement is not a sqlparser.CreateTable or its table spec is missing, so the CREATE TABLE statement cannot be analyzed. It is a defensive internal check that normally only fires if the stored schema is not a plain CREATE TABLE statement.
Source
Thrown at go/vt/vttablet/tabletmanager/vreplication/vreplicator.go:896
if err != nil {
return nil, err
}
// schema should never be nil, but check to be extra safe.
if schema == nil || len(schema.TableDefinitions) != 1 {
return nil, fmt.Errorf("unexpected number of table definitions returned from GetSchema call for table %q: %d",
tableName, len(schema.TableDefinitions))
}
tableSchema := schema.TableDefinitions[0].Schema
var secondaryKeys []*sqlparser.IndexDefinition
parsedDDL, err := vr.vre.env.Parser().ParseStrictDDL(tableSchema)
if err != nil {
return secondaryKeys, err
}
createTable, ok := parsedDDL.(*sqlparser.CreateTable)
// createTable or createTable.TableSpec should never be nil
// if it was a valid cast, but check to be extra safe.
if !ok || createTable == nil || createTable.GetTableSpec() == nil {
return nil, fmt.Errorf("could not determine CREATE TABLE statement from table schema %q", tableSchema)
}
tableSpec := createTable.GetTableSpec()
fkIndexCols := make(map[string]bool)
for _, constraint := range tableSpec.Constraints {
if fkDef, ok := constraint.Details.(*sqlparser.ForeignKeyDefinition); ok {
fkCols := make([]string, len(fkDef.Source))
for i, fkCol := range fkDef.Source {
fkCols[i] = fkCol.Lowered()
}
fkIndexCols[strings.Join(fkCols, ",")] = true
}
}
for _, index := range tableSpec.Indexes {
if index.Info.Type != sqlparser.IndexTypePrimary {
cols := make([]string, len(index.Columns))
for i, col := range index.Columns {
cols[i] = col.Column.Lowered()View on GitHub (pinned to 01a25a7d17)
Solutions
- Inspect the target table's SHOW CREATE TABLE output and confirm it is a plain CREATE TABLE (not a view or non-table object) for the table named in the error
- Retry the workflow; if the schema was edited mid-copy, restore the expected schema or recreate the table and restart MoveTables/Migrate/Reshard
- Check the Vitess version for parser limitations with the DDL features used (e.g. exotic index/constraint syntax) and upgrade if a fix exists
- If it persists, file an issue with the table schema — this is a defensive check that should not fire for valid CREATE TABLE output
Defensive patterns
Strategy: validation
Validate before calling
schema, _ := mysqld.GetSchema(ctx, dbName, &tabletmanagerdatapb.GetSchemaRequest{Tables: []string{tableName}})
stmt, err := parser.ParseStrictDDL(schema.TableDefinitions[0].Schema)
if err != nil { return err }
if _, ok := stmt.(*sqlparser.CreateTable); !ok || stmt.(*sqlparser.CreateTable).GetTableSpec() == nil {
return fmt.Errorf("table %s schema is not a plain CREATE TABLE; fix before starting workflow", tableName)
} Type guard
func isPlainCreateTable(stmt sqlparser.Statement) (*sqlparser.CreateTable, bool) {
ct, ok := stmt.(*sqlparser.CreateTable)
if !ok || ct == nil || ct.GetTableSpec() == nil {
return nil, false
}
return ct, true
} Prevention
- Run SHOW CREATE TABLE on the target table before starting MoveTables/Migrate and confirm it is a plain CREATE TABLE, not a view
- Avoid manually editing table schemas on target tablets while a copy phase is running
- Keep Vitess updated — parser gaps with newer MySQL/MariaDB DDL syntax are fixed over time
- Test the workflow on a staging copy of the schema if you use exotic DDL features
When it happens
Trigger: getTableSecondaryKeys (called from stashSecondaryKeys and execPostCopyActions) runs GetSchema for a table, parses the schema with ParseStrictDDL, and the result fails the (*sqlparser.CreateTable) type assertion, is nil, or GetTableSpec() returns nil — e.g. the schema text is not a plain CREATE TABLE (views, unusual dialect syntax, or an unexpectedly truncated/modified schema).
Common situations: Moving or migrating a table whose schema string on the target tablet is not a standard MySQL CREATE TABLE statement; running a workflow against a view or table whose schema was manually edited; parser incompatibility with MariaDB/MySQL-specific DDL that Vitess's parser mishandles.
Related errors
- table expression is complex
- error parsing vschema statement `%s`: %v
- error parsing vschema statement `%s`: not a ddl statement
- %w in keyspace %s for %s
- vreplication streams are not frozen on tablet %d
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/93e86c9b80e85a60.
Report an issue: GitHub.