vitessio/vitess · error

can't parse binlog event, invalid data: %#v

Error message

can't parse binlog event, invalid data: %#v

What it means

parseEvents validates every raw binlog event buffer with ev.IsValid() before decoding fields. If the event's byte buffer is too short or malformed to even contain a valid header, the streamer aborts with this message including the raw event dump. This indicates corrupt or truncated binlog data from the server.

Source

Thrown at go/vt/binlog/binlog_streamer.go:314

		var ok bool

		select {
		case ev, ok = <-events:
			if !ok {
				// events channel has been closed, which means the connection died.
				log.Info("reached end of binlog event stream")
				return pos, ErrServerEOF
			}
		case err = <-errs:
			return pos, err
		case <-ctx.Done():
			log.Info("stopping early due to binlog Streamer service shutdown or client disconnect")
			return pos, ctx.Err()
		}

		// Validate the buffer before reading fields from it.
		if !ev.IsValid() {
			return pos, 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() {
			format, err = ev.Format()
			if err != nil {
				return pos, fmt.Errorf("can't parse FORMAT_DESCRIPTION_EVENT: %v, event data: %#v", err, ev)
			}
			continue
		}

		// We can't parse anything until we get a FORMAT_DESCRIPTION_EVENT that
		// tells us the size of the event header.
		if 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

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Verify the server's binlog files with mysqlbinlog on the affected log file to confirm corruption
  2. Check for proxies or packet mangling between vttablet and MySQL; bypass them
  3. Fail over to a healthy replica whose binlogs are intact and restart the stream from the last good GTID position
  4. Report to Vitess if it reproduces consistently against a supported MySQL version (possible parser bug)
Defensive patterns

Strategy: try-catch

Try / catch

if err := streamer.Stream(ctx); err != nil {
	if strings.Contains(err.Error(), "invalid data") {
		// corrupt event: verify binlog with mysqlbinlog, fail over, restart from good GTID
	}
}

Prevention

When it happens

Trigger: During Stream/parseEvents, the events channel delivers a mysql.BinlogEvent whose underlying buffer fails IsValid() — e.g. an event shorter than the binlog header, or corrupted packet data from the binlog dump.

Common situations: Binlog files corrupted on disk; a buggy/proxying layer truncating binlog dump packets; reading binlogs from a non-MySQL or patched server emitting malformed events; memory/network corruption.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/1357f1edd35ae80f. Report an issue: GitHub.