vitessio/vitess · error
%v has an extra table named %v
Error message
%v has an extra table named %v
What it means
During the sorted merge of TableDefinitions, when the left tablet has a table whose name sorts before the right's current table, the left side has a table the right side lacks. This error records the extra table name — unless it is a Vitess internal operation table, which is silently skipped.
Source
Thrown at go/vt/mysqlctl/tmutils/schema.go:234
func DiffSchema(leftName string, left *tabletmanagerdatapb.SchemaDefinition, rightName string, right *tabletmanagerdatapb.SchemaDefinition, er concurrency.ErrorRecorder) {
if left == nil && right == nil {
return
}
if left == nil || right == nil {
er.RecordError(fmt.Errorf("schemas are different:\n%s: %v, %s: %v", leftName, left, rightName, right))
return
}
if left.DatabaseSchema != right.DatabaseSchema {
er.RecordError(fmt.Errorf("schemas are different:\n%s: %v\n differs from:\n%s: %v", leftName, left.DatabaseSchema, rightName, right.DatabaseSchema))
}
leftIndex := 0
rightIndex := 0
for leftIndex < len(left.TableDefinitions) && rightIndex < len(right.TableDefinitions) {
// extra table on the left side
if left.TableDefinitions[leftIndex].Name < right.TableDefinitions[rightIndex].Name {
if !schema.IsInternalOperationTableName(left.TableDefinitions[leftIndex].Name) {
er.RecordError(fmt.Errorf("%v has an extra table named %v", leftName, left.TableDefinitions[leftIndex].Name))
}
leftIndex++
continue
}
// extra table on the right side
if left.TableDefinitions[leftIndex].Name > right.TableDefinitions[rightIndex].Name {
if !schema.IsInternalOperationTableName(right.TableDefinitions[rightIndex].Name) {
er.RecordError(fmt.Errorf("%v has an extra table named %v", rightName, right.TableDefinitions[rightIndex].Name))
}
rightIndex++
continue
}
// same name, let's see content
if left.TableDefinitions[leftIndex].Schema != right.TableDefinitions[rightIndex].Schema {
if !schema.IsInternalOperationTableName(left.TableDefinitions[leftIndex].Name) {
er.RecordError(fmt.Errorf("schemas differ on table %v:\n%s: %v\n differs from:\n%s: %v", left.TableDefinitions[leftIndex].Name, leftName, left.TableDefinitions[leftIndex].Schema, rightName, right.TableDefinitions[rightIndex].Schema))View on GitHub (pinned to 01a25a7d17)
Solutions
- Apply the missing CREATE TABLE on the right tablet (via controlled replication catch-up or manual apply)
- Or drop the extra table on the left tablet if it is stale/scratch
- Repair replication so future DDL propagates to both tablets
Example fix
// before -- tablet A has table tmp_migration_state; tablet B does not // after (on tablet A's MySQL) DROP TABLE tmp_migration_state;
Defensive patterns
Strategy: validation
Validate before calling
leftNames := tableNames(left)
rightNames := tableNames(right)
if extra := missing(leftNames, rightNames); len(extra) > 0 {
log.Warn("tables missing on right", slog.Any("tables", extra))
} Try / catch
er := concurrency.AllErrorRecorder{}
tmutils.DiffSchema("left", left, "right", right, &er)
if er.HasErrors() {
return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "schema drift detected: %w", er.Error())
} Prevention
- Use vtctldclient ApplySchema instead of manual DDL on individual tablets
- Fix replication lag before applying schema changes
- Clean up scratch/ghost tables in the same migration that creates them
- Run scheduled schema diffs across shards
When it happens
Trigger: DiffSchema finds left.TableDefinitions contains a table name absent from right.TableDefinitions (left name < right name during the merge walk).
Common situations: A table was created only on one replica (replication broken or skipped DDL); a leftover scratch table on one tablet; an online schema change left its old ghost table on one side.
Related errors
- schemas are different: %s: %v, %s: %v
- schemas are different: %s: %v differs from: %s: %v
- schemas differ on table %v: %s: %v differs from: %s: %v
- permissions differ on %v %v: %s: %v differs from: %s: %v
- SHOW BINARY LOGS returned no rows
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/9d3c0fd5d0aeaf62.
Report an issue: GitHub.