{"record":{"id":"9d3c0fd5d0aeaf62","repo":"vitessio/vitess","slug":"v-has-an-extra-table-named-v","errorCode":null,"errorMessage":"%v has an extra table named %v","messagePattern":"(.+?) has an extra table named (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/tmutils/schema.go","lineNumber":234,"sourceCode":"func DiffSchema(leftName string, left *tabletmanagerdatapb.SchemaDefinition, rightName string, right *tabletmanagerdatapb.SchemaDefinition, er concurrency.ErrorRecorder) {\n\tif left == nil && right == nil {\n\t\treturn\n\t}\n\tif left == nil || right == nil {\n\t\ter.RecordError(fmt.Errorf(\"schemas are different:\\n%s: %v, %s: %v\", leftName, left, rightName, right))\n\t\treturn\n\t}\n\tif left.DatabaseSchema != right.DatabaseSchema {\n\t\ter.RecordError(fmt.Errorf(\"schemas are different:\\n%s: %v\\n differs from:\\n%s: %v\", leftName, left.DatabaseSchema, rightName, right.DatabaseSchema))\n\t}\n\n\tleftIndex := 0\n\trightIndex := 0\n\tfor leftIndex < len(left.TableDefinitions) && rightIndex < len(right.TableDefinitions) {\n\t\t// extra table on the left side\n\t\tif left.TableDefinitions[leftIndex].Name < right.TableDefinitions[rightIndex].Name {\n\t\t\tif !schema.IsInternalOperationTableName(left.TableDefinitions[leftIndex].Name) {\n\t\t\t\ter.RecordError(fmt.Errorf(\"%v has an extra table named %v\", leftName, left.TableDefinitions[leftIndex].Name))\n\t\t\t}\n\t\t\tleftIndex++\n\t\t\tcontinue\n\t\t}\n\n\t\t// extra table on the right side\n\t\tif left.TableDefinitions[leftIndex].Name > right.TableDefinitions[rightIndex].Name {\n\t\t\tif !schema.IsInternalOperationTableName(right.TableDefinitions[rightIndex].Name) {\n\t\t\t\ter.RecordError(fmt.Errorf(\"%v has an extra table named %v\", rightName, right.TableDefinitions[rightIndex].Name))\n\t\t\t}\n\t\t\trightIndex++\n\t\t\tcontinue\n\t\t}\n\n\t\t// same name, let's see content\n\t\tif left.TableDefinitions[leftIndex].Schema != right.TableDefinitions[rightIndex].Schema {\n\t\t\tif !schema.IsInternalOperationTableName(left.TableDefinitions[leftIndex].Name) {\n\t\t\t\ter.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))","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/tmutils/schema.go#L216-L252","documentation":"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.","triggerScenarios":"DiffSchema finds left.TableDefinitions contains a table name absent from right.TableDefinitions (left name < right name during the merge walk).","commonSituations":"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.","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"],"exampleFix":"// before\n-- tablet A has table tmp_migration_state; tablet B does not\n// after (on tablet A's MySQL)\nDROP TABLE tmp_migration_state;","handlingStrategy":"validation","validationCode":"leftNames := tableNames(left)\nrightNames := tableNames(right)\nif extra := missing(leftNames, rightNames); len(extra) > 0 {\n    log.Warn(\"tables missing on right\", slog.Any(\"tables\", extra))\n}","typeGuard":null,"tryCatchPattern":"er := concurrency.AllErrorRecorder{}\ntmutils.DiffSchema(\"left\", left, \"right\", right, &er)\nif er.HasErrors() {\n    return vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"schema drift detected: %w\", er.Error())\n}","preventionTips":["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"],"tags":["schema","consistency-check","mysql","vitess"],"backgroundTag":"schema-drift-between-tablets","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}