vitessio/vitess · error
got a real event before FORMAT_DESCRIPTION_EVENT: %#v
Error message
got a real event before FORMAT_DESCRIPTION_EVENT: %#v
What it means
vstreamer refuses to parse any binlog event that arrives before the FORMAT_DESCRIPTION_EVENT. Only a fake ROTATE_EVENT (sent by the primary to announce the current log file name) is legal before it, because the FORMAT_DESCRIPTION_EVENT establishes the event format (including checksum layout) needed to decode everything else. Any other event at that point means the stream is malformed or mis-sequenced.
Source
Thrown at go/vt/vttablet/tabletserver/vstreamer/vstreamer.go:548
var err error
vs.format, err = ev.Format()
if err != nil {
return nil, fmt.Errorf("can't parse FORMAT_DESCRIPTION_EVENT: %v, event data: %#v", err, ev)
}
vs.eventGTID = nil
return nil, nil
}
// We can't parse anything until we get a FORMAT_DESCRIPTION_EVENT that
// tells us the size of the event header.
if vs.format.IsZero() {
// The only thing that should come before the FORMAT_DESCRIPTION_EVENT
// is a fake ROTATE_EVENT, which the primary sends to tell us the name
// of the current log file.
if ev.IsRotate() {
return nil, nil
}
return nil, 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(vs.format)
if err != nil {
return nil, fmt.Errorf("can't strip checksum from binlog event: %v, event data: %#v", err, ev)
}
shouldSend := func(evType binlogdatapb.VEventType) bool {
if vs.eventTypesToStream != nil && !vs.eventTypesToStream[evType] {
return false
}
return true
}
timeNowUnixNano := time.Now().UnixNano()
var vevents []*binlogdatapb.VEvent
switch {View on GitHub (pinned to 01a25a7d17)
Solutions
- Verify the starting GTID/position points to a valid point in a binlog file where a FORMAT_DESCRIPTION_EVENT precedes your position
- Restart the VStream from the beginning of a binlog file or from a known-good GTID
- Check for proxies/binlog filters between Vitess and MySQL that may strip the FORMAT_DESCRIPTION_EVENT
- Confirm the primary's binlog files are intact (mysqlbinlog the file at that position)
Defensive patterns
Strategy: retry
Validate before calling
// Before streaming, sanity check the binlog file at the start position: // mysqlbinlog --start-position=<pos> <logfile> | head // The first event must be FORMAT_DESCRIPTION_EVENT (or a fake ROTATE).
Try / catch
err := streamErr
if strings.Contains(err.Error(), "got a real event before FORMAT_DESCRIPTION_EVENT") {
// restart the vstream from the beginning of the binlog file / valid GTID
} Prevention
- Always start streams at file-beginning positions or valid GTIDs
- Keep binlog files intact and avoid intermediaries that reorder events
- Monitor for failovers that change binlog file naming mid-stream
When it happens
Trigger: parseEvent receives a real event (not a ROTATE_EVENT) while vs.format is still unset, i.e. before the server has sent the FORMAT_DESCRIPTION_EVENT on the binlog connection.
Common situations: Streaming from a server whose binlog stream starts mid-file without a format description; a replication bug or middleware/proxy that drops or reorders the initial events; resuming from a bad starting position on the binlog file.
Related errors
- GetPreviousGTIDs: previous GTIDs not found
- startPos.GTIDSet is wrong type - expected filePosGTID, got:
- failed to set @source_binlog_checksum=@@global.binlog_checks
- failed to get primary position: %v
- failed to send the ComBinlogDump command: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/882ba59dfaf6ddfa.
Report an issue: GitHub.