vitessio/vitess · error

empty create database statement for

Error message

empty create database statement for %v

What it means

GetSchema runs `SHOW CREATE DATABASE` to capture the database creation statement. If MySQL returns no rows for that statement (no create command available), this error is thrown and schema export aborts.

Solutions

  1. Verify the database exists: run `SHOW CREATE DATABASE <name>` manually with the exact name
  2. Confirm the keyspace/db name spelling and case matches what MySQL knows
  3. Re-fetch after any concurrent DROP/CREATE migration finishes
  4. Check the MySQL variant/proxy implements SHOW CREATE DATABASE with rows

Example fix

// before: GetSchema(ctx, "VtData", ...) for a dropped db
// after: ensure db exists first
// CREATE DATABASE IF NOT EXISTS `VtData`; then retry GetSchema
Defensive patterns

Strategy: try-catch

Validate before calling

qr, err := mysqld.FetchSuperQuery(ctx, "SHOW DATABASES LIKE '"+dbName+"'")
if err == nil && len(qr.Rows) == 0 {
    return fmt.Errorf("database %s does not exist", dbName)
}

Try / catch

sd, err := mysqld.GetSchema(ctx, dbName, nil, nil, false)
if err != nil && strings.Contains(err.Error(), "empty create database statement") {
    log.Warn("database missing or unreportable; recreating before retry", slog.String("db", dbName))
    return retryAfterCreateDatabase(dbName)
}

Prevention

When it happens

Trigger: Calling mysqld.GetSchema for a database where SHOW CREATE DATABASE returns zero rows — e.g. the database was dropped concurrently, an unusual empty/nonexistent db name, or a server not returning the create statement.

Common situations: Race between database drop and schema fetch; querying a db name with case/charset mismatch so MySQL resolves nothing; against proxies that don't implement SHOW CREATE DATABASE rows properly.

Related errors


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

Appendix: source

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

		encodedTables[i] = sqltypes.EncodeStringSQL(tableName)
	}

	return "(" + strings.Join(encodedTables, ", ") + ")", nil
}

// GetSchema returns the schema for database for tables listed in
// tables. If tables is empty, return the schema for all tables.
func (mysqld *Mysqld) GetSchema(ctx context.Context, dbName string, request *tabletmanagerdatapb.GetSchemaRequest) (*tabletmanagerdatapb.SchemaDefinition, error) {
	sd := &tabletmanagerdatapb.SchemaDefinition{}
	backtickDBName := sqlescape.EscapeID(dbName)

	// get the database creation command
	qr, fetchErr := mysqld.FetchSuperQuery(ctx, "SHOW CREATE DATABASE IF NOT EXISTS "+backtickDBName)
	if fetchErr != nil {
		return nil, fetchErr
	}
	if len(qr.Rows) == 0 {
		return nil, fmt.Errorf("empty create database statement for %v", dbName)
	}
	sd.DatabaseSchema = strings.Replace(qr.Rows[0][1].ToString(), backtickDBName, "{{.DatabaseName}}", 1)

	tds, err := mysqld.collectBasicTableData(ctx, dbName, request.Tables, request.ExcludeTables, request.IncludeViews)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	allErrors := &concurrency.AllErrorRecorder{}

	eg, ctx := errgroup.WithContext(ctx)
	eg.SetLimit(getSchemaConcurrency)

	// Get per-table schema concurrently.
	tableNames := make([]string, 0, len(tds))

View on GitHub (pinned to 01a25a7d17)