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

  1. 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
  2. Retry the workflow; if the schema was edited mid-copy, restore the expected schema or recreate the table and restart MoveTables/Migrate/Reshard
  3. Check the Vitess version for parser limitations with the DDL features used (e.g. exotic index/constraint syntax) and upgrade if a fix exists
  4. 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

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


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