vitessio/vitess · critical
can't parse binlog event: invalid data: %#v
Error message
can't parse binlog event: invalid data: %#v
What it means
parseEvent rejects any binlog event that fails ev.IsValid() — the raw event bytes from the MySQL binlog connection are malformed/truncated and cannot be decoded. This is a hard data-integrity failure of the binlog stream.
Source
Thrown at go/vt/vttablet/tabletserver/vstreamer/vstreamer.go:523
if err := injectHeartbeat(!ok, checkResult.Summary()); err != nil {
if err == io.EOF {
return nil
}
vs.vse.errorCounts.Add("Send", 1)
return vterrors.Wrapf(err, "failed to send heartbeat event")
}
}
}
}
// parseEvent parses an event from the binlog and converts it to a list of VEvents.
// The bufferAndTransmit function must be passed if the event is a TransactionPayloadEvent
// as for larger payloads (> ZstdInMemoryDecompressorMaxSize) the internal events need
// to be streamed directly here in order to avoid holding the entire payload's contents,
// which can be 10s or even 100s of GiBs, all in memory.
func (vs *vstreamer) parseEvent(ev mysql.BinlogEvent, bufferAndTransmit func(vevent *binlogdatapb.VEvent) error) ([]*binlogdatapb.VEvent, error) {
if !ev.IsValid() {
return nil, fmt.Errorf("can't parse binlog event: invalid data: %#v", ev)
}
// We need to keep checking for FORMAT_DESCRIPTION_EVENT even after we've
// seen one, because another one might come along (e.g. on log rotate due to
// binlog settings change) that changes the format.
if ev.IsFormatDescription() {
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() {View on GitHub (pinned to 01a25a7d17)
Solutions
- Check mysqld logs and run CHECK TABLE / verify binlog integrity on the source; corruption is usually on the MySQL side.
- Restart the vstreamer from an earlier GTID or from the start of the current binlog file; if the file is corrupt, purge/rotate binlogs and resync the workflow.
- Compare MySQL server version with vitess support matrix; if using an exotic binlog format/feature (e.g. unusual encryption), disable it or upgrade vitess.
- If reproducible on healthy binlogs, capture the event dump (%#v output) and file a vitess bug with the MySQL version.
Defensive patterns
Strategy: retry
Try / catch
err := vs.streamLog(ctx)
if err != nil && strings.Contains(err.Error(), "can't parse binlog event") {
// binlog corruption: restart from an earlier GTID / rotate logs, then resync
restartFromEarlierGTID(ctx)
if stillFailing { resyncWorkflow(ctx) }
} Prevention
- Monitor MySQL binlog integrity and disk health on the source
- Keep MySQL versions within vitess's supported matrix
- Avoid hard-killing mysqld; use graceful shutdowns
- Restart vstreams from a known-good GTID after binlog issues
When it happens
Trigger: mysql.BinlogEvent delivered by the binlog connection where IsValid() returns false — truncated or corrupt event buffer, protocol desync, or garbage bytes from the binlog dump.
Common situations: Corrupted binlog files on disk (disk issues, abnormal mysqld kill), network truncation between mysqld and the tablet, MySQL/binlog format incompatibilities, binlog rotated mid-read with corruption.
Related errors
- can't strip checksum from binlog event: %v, event data: %#v
- error reading binlog event %v: %v
- first event from binlog %v is not valid
- can't parse binlog event, invalid data: %#v
- can't strip checksum from binlog event: %v, event data: %#v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/d354bf9fe8dc8910.
Report an issue: GitHub.