{"record":{"id":"4c695cfffe1b133e","repo":"vitessio/vitess","slug":"the-receiver-replicationstatus-contained-a-mysql56","errorCode":null,"errorMessage":"The receiver ReplicationStatus contained a Mysql56GTIDSet in its relay log, but a replica's ReplicationStatus is of another flavor. This should never happen.","messagePattern":"The receiver ReplicationStatus contained a Mysql56GTIDSet in its relay log, but a replica's ReplicationStatus is of another flavor\\. This should never happen\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/replication/replication_status.go","lineNumber":212,"sourceCode":"// provided as a list of Positions. This method only works if the flavor for all retrieved Positions is MySQL.\n// The result is returned as a Mysql56GTIDSet, each of whose elements is a found errant GTID.\n// 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.\nfunc FindErrantGTIDs(position Position, sourceUUID SID, otherPositions []Position) (Mysql56GTIDSet, error) {\n\tif len(otherPositions) == 0 {\n\t\t// If there is nothing to compare this replica against, then we must assume that its GTID set is the correct one.\n\t\treturn nil, nil\n\t}\n\n\tgtidSet, ok := position.GTIDSet.(Mysql56GTIDSet)\n\tif !ok {\n\t\treturn nil, errors.New(\"errant GTIDs can only be computed on the MySQL flavor\")\n\t}\n\n\totherSets := make([]Mysql56GTIDSet, 0, len(otherPositions))\n\tfor _, pos := range otherPositions {\n\t\totherSet, ok := pos.GTIDSet.(Mysql56GTIDSet)\n\t\tif !ok {\n\t\t\tpanic(\"The receiver ReplicationStatus contained a Mysql56GTIDSet in its relay log, but a replica's ReplicationStatus is of another flavor. This should never happen.\")\n\t\t}\n\t\totherSets = append(otherSets, otherSet)\n\t}\n\n\t// Copy set for final diffSet so we don't mutate receiver.\n\tdiffSet := make(Mysql56GTIDSet, len(gtidSet))\n\tfor sid, intervals := range gtidSet {\n\t\tif sid == sourceUUID {\n\t\t\tcontinue\n\t\t}\n\t\tdiffSet[sid] = intervals\n\t}\n\n\tfor _, otherSet := range otherSets {\n\t\tdiffSet = diffSet.Difference(otherSet)\n\t}\n\n\tif len(diffSet) == 0 {","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/replication/replication_status.go#L194-L230","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nerrant, err := status.FindErrantGTIDs(otherStatuses) // otherStatuses contains a MariaDB-flavor status\n// after\nfor i, st := range otherStatuses {\n    if _, ok := st.RelayLogPosition.GTIDSet.(mysql.Mysql56GTIDSet); !ok {\n        return fmt.Errorf(\"status %d is not MySQL56 GTID flavor; skipping\", i)\n    }\n}\nerrant, err := status.FindErrantGTIDs(otherStatuses)","handlingStrategy":"type-guard","validationCode":"for _, pos := range otherPositions {\n    if _, ok := pos.GTIDSet.(mysql.Mysql56GTIDSet); !ok {\n        return fmt.Errorf(\"cannot compare GTID flavors: %T\", pos.GTIDSet)\n    }\n}","typeGuard":"func isMysql56GTIDSet(s mysql.GTIDSet) bool {\n    _, ok := s.(mysql.Mysql56GTIDSet)\n    return ok\n}","tryCatchPattern":"defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"FindErrantGTIDs flavor mismatch: %v\", r) } }()","preventionTips":["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."],"tags":["mysql","replication","gtid","panic"],"backgroundTag":"gtid-flavor-mismatch","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}