vitessio/vitess · error
The receiver ReplicationStatus contained a Mysql56GTIDSet in
Error message
The receiver ReplicationStatus contained a Mysql56GTIDSet in its relay log, but a replica's ReplicationStatus is of another flavor. This should never happen.
What it means
FindErrantGTIDs computes errant transactions by diffing the receiver's Mysql56GTIDSet relay-log GTID set against GTID sets from other replica positions. It panics if any otherPositions entry holds a GTIDSet of a different flavor (e.g. MariaDB GTIDSet) while the receiver holds a Mysql56GTIDSet, since GTID sets of different flavors cannot be compared. This guards an invariant that all compared statuses come from the same GTID flavor.
Source
Thrown at go/mysql/replication/replication_status.go:212
// provided as a list of Positions. This method only works if the flavor for all retrieved Positions is MySQL.
// The result is returned as a Mysql56GTIDSet, each of whose elements is a found errant GTID.
// This function is best effort in nature. If it marks something as errant, then it is for sure errant. But there may be cases of errant GTIDs, which aren't caught by this function.
func FindErrantGTIDs(position Position, sourceUUID SID, otherPositions []Position) (Mysql56GTIDSet, error) {
if len(otherPositions) == 0 {
// If there is nothing to compare this replica against, then we must assume that its GTID set is the correct one.
return nil, nil
}
gtidSet, ok := position.GTIDSet.(Mysql56GTIDSet)
if !ok {
return nil, errors.New("errant GTIDs can only be computed on the MySQL flavor")
}
otherSets := make([]Mysql56GTIDSet, 0, len(otherPositions))
for _, pos := range otherPositions {
otherSet, ok := pos.GTIDSet.(Mysql56GTIDSet)
if !ok {
panic("The receiver ReplicationStatus contained a Mysql56GTIDSet in its relay log, but a replica's ReplicationStatus is of another flavor. This should never happen.")
}
otherSets = append(otherSets, otherSet)
}
// Copy set for final diffSet so we don't mutate receiver.
diffSet := make(Mysql56GTIDSet, len(gtidSet))
for sid, intervals := range gtidSet {
if sid == sourceUUID {
continue
}
diffSet[sid] = intervals
}
for _, otherSet := range otherSets {
diffSet = diffSet.Difference(otherSet)
}
if len(diffSet) == 0 {View on GitHub (pinned to 01a25a7d17)
Solutions
- Verify all tablets in the keyspace use the same GTID mode (mysql56) via SHOW VARIABLES LIKE 'gtid_mode' / vitess init flags.
- Ensure every ReplicationStatus passed to FindErrantGTIDs comes from MySQL56-flavor tablets; filter or convert otherPositions first.
- Re-initialize mismatched tablets with the correct -init_gtid_mode / flavor configuration.
Example fix
// before
errant, err := status.FindErrantGTIDs(otherStatuses) // otherStatuses contains a MariaDB-flavor status
// after
for i, st := range otherStatuses {
if _, ok := st.RelayLogPosition.GTIDSet.(mysql.Mysql56GTIDSet); !ok {
return fmt.Errorf("status %d is not MySQL56 GTID flavor; skipping", i)
}
}
errant, err := status.FindErrantGTIDs(otherStatuses) Defensive patterns
Strategy: type-guard
Validate before calling
for _, pos := range otherPositions {
if _, ok := pos.GTIDSet.(mysql.Mysql56GTIDSet); !ok {
return fmt.Errorf("cannot compare GTID flavors: %T", pos.GTIDSet)
}
} Type guard
func isMysql56GTIDSet(s mysql.GTIDSet) bool {
_, ok := s.(mysql.Mysql56GTIDSet)
return ok
} Try / catch
defer func() { if r := recover(); r != nil { err = fmt.Errorf("FindErrantGTIDs flavor mismatch: %v", r) } }() Prevention
- Enforce uniform gtid_mode (mysql56) across all tablets in the keyspace.
- Check the GTID flavor of every status before running errant-GTID detection.
- Avoid mixing MySQL and MariaDB replicas in the same shard.
When it happens
Trigger: Calling FindErrantGTIDs or findErrantGTIDs with a mix of ReplicationStatus values where the receiver uses MySQL 5.6 GTIDs but at least one otherPositions entry carries a non-MySQL56 GTIDSet (e.g. MariaDB flavor).
Common situations: Cluster with mixed MySQL and MariaDB replicas; reparenting/emergency operations (EmergencyReparentShard) run across a keyspace where one tablet was initialized with a different GTID mode; config drift where some tablets run with gtid_mode=OFF/MariaDB style.
Related errors
- GetPreviousGTIDs: previous GTIDs not found
- startPos.GTIDSet is wrong type - expected filePosGTID, got:
- failed to get primary position: %v
- stream error @ (including the GTID we failed to process) %v:
- panic(err)
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/4c695cfffe1b133e.
Report an issue: GitHub.