vitessio/vitess · error
unexpected number of table definitions returned from GetSche
Error message
unexpected number of table definitions returned from GetSchema call for table %q: %d
What it means
getTableSecondaryKeys asks mysqld.GetSchema for exactly the one table being processed and expects exactly one TableDefinition. If the result is nil, empty, or contains more than one definition, this error is raised. It guards against silently parsing the wrong table's schema when stashing secondary keys or running post-copy actions.
Source
Thrown at go/vt/vttablet/tabletmanager/vreplication/vreplicator.go:883
return nil
}
}
return err
}
}
return nil
}
func (vr *vreplicator) getTableSecondaryKeys(ctx context.Context, tableName string) ([]*sqlparser.IndexDefinition, error) {
req := &tabletmanagerdatapb.GetSchemaRequest{Tables: []string{tableName}}
schema, err := vr.mysqld.GetSchema(ctx, vr.dbClient.DBName(), req)
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 {View on GitHub (pinned to 01a25a7d17)
Solutions
- Confirm the table still exists in the target database and its name casing matches (check lower_case_table_names on the target mysqld).
- Verify vr.dbClient.DBName() is the expected database — an empty or wrong dbname makes GetSchema return no rows.
- Check concurrent operations: a DropTable/RENAME during copy causes the table to vanish; re-run the table copy (MarkTableCopied/reset copy_state and restart).
- Inspect the %d count in the message: 0 means missing table, >1 means unexpected GetSchema behavior — investigate the mysqld/schema engine accordingly.
Example fix
// before: table was renamed mid-copy so GetSchema returns 0 definitions // after: verify the table exists before/at copy time // mysql> SHOW CREATE TABLE customer.corder; // then restart the failed table copy: // UPDATE _vt.copy_state SET ... WHERE vrepl_id=<id>; -- or re-run MoveTables for that table
Defensive patterns
Strategy: validation
Validate before calling
// Verify the table exists exactly once in the target db before copy actions: // SELECT COUNT(*) FROM information_schema.tables // WHERE table_schema = '<dbname>' AND table_name = '<table>'; -- expect 1
Try / catch
schema, err := vr.mysqld.GetSchema(ctx, vr.dbClient.DBName(), req)
if err != nil {
return nil, vterrors.Wrapf(err, "GetSchema failed for %s", tableName)
}
if schema == nil || len(schema.TableDefinitions) != 1 {
// count in message: 0 = table missing (dropped/renamed), >1 = unexpected
return nil, fmt.Errorf("unexpected number of table definitions for %q", tableName)
} Prevention
- Avoid concurrent DROP/RENAME of tables being copied by MoveTables.
- Match table-name casing with lower_case_table_names on the target.
- Confirm the workflow targets the intended keyspace/dbname.
- Re-run the affected table's copy after schema churn resolves.
When it happens
Trigger: GetSchema returns zero definitions (table dropped/renamed between planning and this call, wrong dbname) or multiple definitions (unusual GetSchema behavior). Guard also covers schema==nil defensively.
Common situations: Table dropped concurrently during a MoveTables copy; case-sensitivity mismatches (lower_case_table_names) causing lookups to miss; pointing the workflow at a different keyspace/dbname than expected; GetSchema filter misconfiguration.
Related errors
- deferring secondary key creation is not supported for %s wor
- cannot migrate while vreplication streams in source shards a
- table %s not found in schema
- primary key column %v not found in table's select filter or
- plan not found for table: %s, current plans are: %#v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/6e32c4e7896d5afc.
Report an issue: GitHub.