vitessio/vitess · error
can't get GTID from binlog event: %v, event data: %#v
Error message
can't get GTID from binlog event: %v, event data: %#v
What it means
For pseudo (e.g. PREVIOUS_GTIDS/anonymous) events, parseEvents extracts the GTID via ev.GTID(format) to track stream position. If GTID extraction fails — the event's GTID format is unsupported or the buffer is malformed — the streamer cannot maintain position and aborts.
Source
Thrown at go/vt/binlog/binlog_streamer.go:350
// is a fake ROTATE_EVENT, which the primary sends to tell us the name
// of the current log file.
if ev.IsRotate() {
continue
}
return pos, fmt.Errorf("got a real event before FORMAT_DESCRIPTION_EVENT: %#v", ev)
}
// Strip the checksum, if any. We don't actually verify the checksum, so discard it.
ev, _, err = ev.StripChecksum(format)
if err != nil {
return pos, fmt.Errorf("can't strip checksum from binlog event: %v, event data: %#v", err, ev)
}
switch {
case ev.IsPseudo():
gtid, _, _, _, err = ev.GTID(format)
if err != nil {
return pos, fmt.Errorf("can't get GTID from binlog event: %v, event data: %#v", err, ev)
}
oldpos := pos
pos = replication.AppendGTID(pos, gtid)
// If the event is received outside of a transaction, it must
// be sent. Otherwise, it will get lost and the targets will go out
// of sync.
if autocommit && !pos.Equal(oldpos) {
if err = commit(ev.Timestamp()); err != nil {
return pos, err
}
}
case ev.IsGTID(): // GTID_EVENT: update current GTID, maybe BEGIN.
var hasBegin bool
gtid, hasBegin, _, _, err = ev.GTID(format)
if err != nil {
return pos, fmt.Errorf("can't get GTID from binlog event: %v, event data: %#v", err, ev)
}
pos = replication.AppendGTID(pos, gtid)View on GitHub (pinned to 01a25a7d17)
Solutions
- Ensure the source server's GTID mode/flavor matches what Vitess expects (gtid_mode=ON for MySQL; matching MariaDB flavor builds)
- Check that the tablet is built with support for the source's GTID flavor
- Validate the binlog with mysqlbinlog to rule out corruption
- Restart the stream from a known-good position; if it persists, upgrade Vitess
- If GTID is intentionally off, confirm the flavor's GTID representation is still parseable by Vitess
Defensive patterns
Strategy: validation
Validate before calling
// confirm GTID mode is configured consistently before streaming // mysql> SELECT @@global.gtid_mode; -- expect ON for MySQL sources
Try / catch
if err := streamer.Stream(ctx); err != nil {
if strings.Contains(err.Error(), "can't get GTID") {
// GTID flavor mismatch/corruption: verify gtid_mode and flavor, restart from good position
}
} Prevention
- Use matching GTID flavors (MySQL vs MariaDB) across the topology
- Set gtid_mode=ON on MySQL sources used for filtered replication
- Validate binlog flavor compatibility when provisioning tablets
When it happens
Trigger: During Stream/parseEvents, ev.IsPseudo() is true and ev.GTID(format) errors — e.g. a GTID flavor (MySQL, MariaDB) the client cannot decode, or corrupt GTID payload bytes.
Common situations: Mixing GTID modes/flavors (MySQL GTID vs MariaDB) across a topology; binlog data from an unsupported server version; corrupted GTID event payload.
Related errors
- GetPreviousGTIDs: previous GTIDs not found
- empty gtid passed to setPosition
- startPos.GTIDSet is wrong type - expected filePosGTID, got:
- invalid FilePos GTID (%v): expecting file:pos
- invalid FilePos GTID (%v): expecting pos to be an integer
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/33e6ec9a00242866.
Report an issue: GitHub.