{"record":{"id":"ef340519c55f5b07","repo":"vitessio/vitess","slug":"schemas-differ-on-table-v-s-v-differs-from","errorCode":null,"errorMessage":"schemas differ on table %v:\n%s: %v\n differs from:\n%s: %v","messagePattern":"schemas differ on table (.+?):\n(.+?): (.+?)\n differs from:\n(.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/tmutils/schema.go","lineNumber":252,"sourceCode":"\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))\n\t\t\t}\n\t\t}\n\n\t\tif left.TableDefinitions[leftIndex].Type != right.TableDefinitions[rightIndex].Type {\n\t\t\tif !schema.IsInternalOperationTableName(right.TableDefinitions[rightIndex].Name) {\n\t\t\t\ter.RecordError(fmt.Errorf(\"schemas differ on table type for table %v:\\n%s: %v\\n differs from:\\n%s: %v\", left.TableDefinitions[leftIndex].Name, leftName, left.TableDefinitions[leftIndex].Type, rightName, right.TableDefinitions[rightIndex].Type))\n\t\t\t}\n\t\t}\n\n\t\tleftIndex++\n\t\trightIndex++\n\t}\n\n\tfor leftIndex < len(left.TableDefinitions) {\n\t\tif left.TableDefinitions[leftIndex].Type == TableBaseTable {\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}","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/tmutils/schema.go#L234-L270","documentation":"When both tablets have a table with the same name but the CREATE TABLE / view definition string differs, DiffSchema records this error showing each side's table schema. Internal operation tables are skipped. This is the core table-level schema drift detection used by vtctldclient Schema Diff workflows.","triggerScenarios":"DiffSchema compares two TableDefinitions with equal names where left.Schema != right.Schema — different columns, indexes, charsets, or view definitions between tablets.","commonSituations":"A migration/ALTER TABLE was applied on the primary but a replica missed it; schema applied out of order across shards; manual column addition on one tablet; a view redefined on only one side.","solutions":["Apply the correct ALTER TABLE (or CREATE VIEW) on the lagging tablet so the definitions match","Use vtctldclient ApplySchema / controlled replication catch-up to propagate the DDL","Run an online schema change tool across all shards to converge the schema","Re-run the schema diff afterward to confirm zero differences"],"exampleFix":"// before\n-- tablet A: orders has column `note VARCHAR(100)`\n-- tablet B: orders lacks `note`\n// after (on tablet B's MySQL)\nALTER TABLE orders ADD COLUMN note VARCHAR(100);","handlingStrategy":"validation","validationCode":"for i, lt := range left.TableDefinitions {\n    for _, rt := range right.TableDefinitions {\n        if lt.Name == rt.Name && lt.Schema != rt.Schema {\n            log.Warn(\"table schema drift\", slog.String(\"table\", lt.Name), slog.String(\"left\", lt.Schema), slog.String(\"right\", rt.Schema))\n        }\n    }\n    _ = i\n}","typeGuard":null,"tryCatchPattern":"er := concurrency.AllErrorRecorder{}\ntmutils.DiffSchema(\"left\", left, \"right\", right, &er)\nif er.HasErrors() {\n    return vterrors.Errorf(vtrpcpb.Code_INTERNAL, \"table schema drift: %w\", er.Error())\n}\n// proceed only when schemas are identical","preventionTips":["Always apply DDL through vtctldclient ApplySchema for atomic, tracked migrations","Run a schema diff before and after every migration as a gate","Keep all shards on the same migration sequence (use online DDL with consistent start)","Monitor replication so DDL never silently skips a tablet"],"tags":["schema","consistency-check","mysql","ddl","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"}