vitessio/vitess · error
schemas are different: %s: %v, %s: %v
Error message
schemas are different: %s: %v, %s: %v
What it means
DiffSchema compares two SchemaDefinition protos from two tablets. If exactly one side is nil, the comparison cannot proceed and this error records that one tablet reported no schema at all (the two inputs are fundamentally different). Note the message prints the whole proto values, which may be '<nil>'.
Source
Thrown at go/vt/mysqlctl/tmutils/schema.go:221
if strings.HasPrefix(line, "CREATE TABLE `") {
lines[i] = strings.Replace(line, "CREATE TABLE `", "CREATE TABLE `{{.DatabaseName}}`.`", 1)
}
}
sqlStrings = append(sqlStrings, strings.Join(lines, "\n"))
}
}
return append(sqlStrings, createViewSQL...)
}
// DiffSchema generates a report on what's different between two SchemaDefinitions
// including views, but Vitess internal tables are ignored.
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
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Fix the underlying schema fetch on the nil side (check tablet health, re-run GetSchema)
- Initialize/restore the empty tablet from a healthy source
- Guard the call: only invoke DiffSchema when both SchemaDefinitions are non-nil, and surface the fetch error instead
Example fix
// before
left, _ := getSchema(ctx, tabletA)
tmutils.DiffSchema("a", left, "b", right, er)
// after
left, err := getSchema(ctx, tabletA)
if err != nil {
er.RecordError(fmt.Errorf("cannot fetch schema from %s: %v", "a", err))
return
}
tmutils.DiffSchema("a", left, "b", right, er) Defensive patterns
Strategy: type-guard
Validate before calling
if left == nil || right == nil {
return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot diff schema: one side is nil (left=%v right=%v)", leftName, rightName)
} Type guard
func bothSchemasPresent(l, r *tabletmanagerdatapb.SchemaDefinition) bool {
return l != nil && r != nil
} Try / catch
left, err := getSchema(ctx, leftTablet)
if err != nil {
return vterrors.Wrapf(err, "cannot fetch schema from %s", leftName)
}
er := concurrency.AllErrorRecorder{}
tmutils.DiffSchema(leftName, left, rightName, right, &er)
if er.HasErrors() {
return er.Error()
} Prevention
- Check tablet health before running schema diffs
- Do not swallow GetSchema errors into nil values
- Initialize new tablets fully before including them in diff workflows
- Alert on tablets returning empty schema definitions
When it happens
Trigger: DiffSchema(leftName, nil, rightName, right, er) or vice versa — e.g. one vttablet's GetSchema RPC failed or returned an empty response before the diff.
Common situations: A tablet is down or unreachable so its schema fetch returned nil; a fresh tablet has not been initialized; the RPC error was swallowed upstream and nil was passed to DiffSchema.
Related errors
- schemas are different: %s: %v differs from: %s: %v
- %v has an extra table named %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/5f7667a9d14a89f8.
Report an issue: GitHub.