{"record":{"id":"1fbc10042bd94531","repo":"vitessio/vitess","slug":"schemas-differ-on-table-type-for-table-v-s-v","errorCode":null,"errorMessage":"schemas differ on table type for table %v:\n%s: %v\n differs from:\n%s: %v","messagePattern":"schemas differ on table type for table (.+?):\n(.+?): (.+?)\n differs from:\n(.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/tmutils/schema.go","lineNumber":258,"sourceCode":"\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}\n\t\t}\n\t\tif left.TableDefinitions[leftIndex].Type == TableView {\n\t\t\ter.RecordError(fmt.Errorf(\"%v has an extra view named %v\", leftName, left.TableDefinitions[leftIndex].Name))\n\t\t}\n\t\tleftIndex++\n\t}","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/tmutils/schema.go#L240-L276","documentation":"DiffSchema compares two tablet schemas field-by-field. When two TableDefinitions with the same name have different TableDefinition.Type values (e.g. one side sees it as a base table, the other as a view), the diff is recorded via the error recorder. Internal operation tables (e.g. those created by online DDL or migration tooling) are excluded to avoid false positives.","triggerScenarios":"Calling DiffSchema/DiffSchemaToArray on two SchemaDefinition protos where left and right both contain a table of the same name but with mismatched Type enum values; the leftIndex/rightIndex cursor has already matched names before this check.","commonSituations":"VDiff or resharding validation comparing schema between source and target shards; a table was converted between a view and a base table on one tablet but not the other; a restored replica diverged from the primary after a manual ALTER; schema upgrade applied to only one shard.","solutions":["Compare the table's type on both tablets with SHOW CREATE TABLE (or SHOW FULL TABLES) and align them via ALTER TABLE / DROP+CREATE.","Re-apply the intended schema to the lagging side using ApplySchema with allowList.","If the mismatching table is a vitess internal operation table, confirm it is matched by schema.IsInternalOperationTableName so it can be safely ignored.","Run vtctldclient ValidateSchema / SchemaCompare to confirm the diff is resolved before resuming the workflow."],"exampleFix":"// before: one shard has a view, other a table\nSHOW FULL TABLES; -- t1: VIEW vs BASE TABLE\n// after: align both\nDROP VIEW t1; CREATE TABLE t1 (...); -- or restore from correct schema","handlingStrategy":"validation","validationCode":"for _, l := range left.TableDefinitions {\n  for _, r := range right.TableDefinitions {\n    if l.Name == r.Name && l.Type != r.Type {\n      return fmt.Errorf(\"type mismatch on %s: %d vs %d\", l.Name, l.Type, r.Type)\n    }\n  }\n}","typeGuard":"func isInternalTable(name string) bool { return schema.IsInternalOperationTableName(name) }","tryCatchPattern":"err := tmutils.DiffSchemaToArray(ctx, left, right, nil)\nif err != nil { log.Errorf(\"schema diff failed: %v\", err); return err }","preventionTips":["Run vtctldclient ValidateSchema regularly across keyspaces","Always deploy schema changes via ApplySchema, not direct MySQL DDL","Include views in every ApplySchema run","Keep backup/restore procedures version-aligned"],"tags":["schema","drift","mysqlctl"],"backgroundTag":"schema-mismatch-between-tablets","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}