{"record":{"id":"fe90f0d32d71f3b7","repo":"vitessio/vitess","slug":"v-has-an-extra-view-named-v","errorCode":null,"errorMessage":"%v has an extra view named %v","messagePattern":"(.+?) has an extra view named (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/tmutils/schema.go","lineNumber":273,"sourceCode":"\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}\n\tfor rightIndex < len(right.TableDefinitions) {\n\t\tif right.TableDefinitions[rightIndex].Type == TableBaseTable {\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}\n\t\tif right.TableDefinitions[rightIndex].Type == TableView {\n\t\t\ter.RecordError(fmt.Errorf(\"%v has an extra view named %v\", rightName, right.TableDefinitions[rightIndex].Name))\n\t\t}\n\t\trightIndex++\n\t}\n}\n\n// DiffSchemaToArray diffs two schemas and return the schema diffs if there is any.\nfunc DiffSchemaToArray(leftName string, left *tabletmanagerdatapb.SchemaDefinition, rightName string, right *tabletmanagerdatapb.SchemaDefinition) (result []string) {","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/tmutils/schema.go#L255-L291","documentation":"Same leftover-tables loop as the extra-table error, but for TableView definitions: a view exists only on the left schema and is reported as 'an extra view named ...'. Unlike extra base tables, internal operation table filtering does NOT apply to views — any unmatched view is reported.","triggerScenarios":"Calling DiffSchema where left.TableDefinitions has a TableView entry with no counterpart on the right after the name walk.","commonSituations":"A view was created on the source keyspace only; a table was converted to a view on one shard; view definitions were excluded from a partial ApplySchema run; backup/restore across versions where views were introduced later.","solutions":["Create the missing view on the other side (ApplySchema with the CREATE VIEW statement) or drop it on the side that has it.","Ensure ApplySchema/SchemaReload was run on all tablets in both keyspaces/shards.","Verify with SHOW FULL TABLES on both tablets which side is correct.","Rerun validation to confirm the diff is gone."],"exampleFix":"// before: view only on left\nvtctldclient ApplySchema --sql \"CREATE VIEW v1 AS SELECT ...\" ks\n// after: view exists on both sides","handlingStrategy":"validation","validationCode":"for _, t := range left.TableDefinitions {\n  if t.Type == TableView { found := false; for _, r := range right.TableDefinitions { if r.Name == t.Name { found = true } }; if !found { return fmt.Errorf(\"missing view %s on right\", t.Name) } }\n}","typeGuard":"func isView(td *tmutils.TableDefinition) bool { return td.Type == tmutils.TableView }","tryCatchPattern":"err := tmutils.DiffSchema(ctx, left, right)\nif err != nil { return fmt.Errorf(\"view/table set diverged: %w\", err) }","preventionTips":["Ship CREATE VIEW statements together with table DDL in ApplySchema migrations","Verify SHOW FULL TABLES parity after view deployments"],"tags":["schema","views","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"}