vitessio/vitess · error

empty create table statement for %v

Error message

empty create table statement for %v

What it means

normalizedSchema executes `SHOW CREATE TABLE db.table` and expects at least one row containing the CREATE statement. Zero rows means MySQL gave no table definition, so normalization fails with this error.

Source

Thrown at go/vt/mysqlctl/schema.go:255

	if !tableSchemaOnly {
		fields, columns, err = mysqld.GetColumns(ctx, dbName, tableName)
		if err != nil {
			return nil, nil, "", err
		}
	}

	return fields, columns, schema, nil
}

// normalizedSchema returns a table schema with database names replaced, and auto_increment annotations removed.
func (mysqld *Mysqld) normalizedSchema(ctx context.Context, dbName, tableName, tableType string) (string, error) {
	backtickDBName := sqlescape.EscapeID(dbName)
	qr, fetchErr := mysqld.FetchSuperQuery(ctx, fmt.Sprintf("SHOW CREATE TABLE %s.%s", backtickDBName, sqlescape.EscapeID(tableName)))
	if fetchErr != nil {
		return "", vterrors.Wrapf(fetchErr, "in Mysqld.normalizedSchema()")
	}
	if len(qr.Rows) == 0 {
		return "", fmt.Errorf("empty create table statement for %v", tableName)
	}

	// Normalize & remove auto_increment because it changes on every insert
	// FIXME(alainjobart) find a way to share this with
	// vt/tabletserver/table_info.go:162
	norm := qr.Rows[0][1].ToString()
	norm = autoIncr.ReplaceAllLiteralString(norm, "")
	if tableType == tmutils.TableView {
		// Views will have the dbname in there, replace it
		// with {{.DatabaseName}}
		norm = strings.ReplaceAll(norm, backtickDBName, "{{.DatabaseName}}")
	}

	return norm, nil
}

// ResolveTables returns a list of actual tables+views matching a list
// of regexps

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Confirm the table exists: run `SHOW CREATE TABLE db.table` manually
  2. Refresh the table list before export (re-run GetSchema after DDL completes)
  3. Check for concurrent schema migrations and retry after they finish
  4. If the table legitimately cannot be shown (permissions), grant SELECT/SHOW privileges to the vt user

Example fix

// before: iterating a stale table list containing dropped_table
// after: re-list tables first
// SHOW TABLES FROM db; then normalizedSchema for existing tables only
Defensive patterns

Strategy: validation

Validate before calling

qr, err := mysqld.FetchSuperQuery(ctx, "SHOW TABLES FROM "+sqlescape.EscapeID(dbName))
if err == nil {
    existing := map[string]bool{}
    for _, r := range qr.Rows { existing[r[0].ToString()] = true }
    if !existing[tableName] {
        return fmt.Errorf("table %s.%s does not exist", dbName, tableName)
    }
}

Try / catch

norm, err := mysqld.NormalizedSchema(ctx, dbName, tableName)
if err != nil && strings.Contains(err.Error(), "empty create table statement") {
    log.Warn("table missing during schema export; refreshing table list")
    return refreshAndRetry(dbName)
}

Prevention

When it happens

Trigger: Calling collectSchema/GetSchema for a table that returns no rows from SHOW CREATE TABLE — typically the table was dropped concurrently, doesn't exist, or the server responds unusually.

Common situations: Schema drift between topodata and MySQL (table dropped while exporting); querying views/materialized structures unsupported by the flavor; stale table lists captured before a DROP.

Related errors


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