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

  1. Confirm the table still exists in the target database and its name casing matches (check lower_case_table_names on the target mysqld).
  2. Verify vr.dbClient.DBName() is the expected database — an empty or wrong dbname makes GetSchema return no rows.
  3. Check concurrent operations: a DropTable/RENAME during copy causes the table to vanish; re-run the table copy (MarkTableCopied/reset copy_state and restart).
  4. 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

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


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