{"record":{"id":"e8ca02af0c35110c","repo":"vitessio/vitess","slug":"can-t-parse-format-description-event-v-event-da","errorCode":null,"errorMessage":"can't parse FORMAT_DESCRIPTION_EVENT: %v, event data: %#v","messagePattern":"can't parse FORMAT_DESCRIPTION_EVENT: (.+?), event data: %#v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/binlog/binlog_streamer.go","lineNumber":323,"sourceCode":"\t\tcase err = <-errs:\n\t\t\treturn pos, err\n\t\tcase <-ctx.Done():\n\t\t\tlog.Info(\"stopping early due to binlog Streamer service shutdown or client disconnect\")\n\t\t\treturn pos, ctx.Err()\n\t\t}\n\n\t\t// Validate the buffer before reading fields from it.\n\t\tif !ev.IsValid() {\n\t\t\treturn pos, fmt.Errorf(\"can't parse binlog event, invalid data: %#v\", ev)\n\t\t}\n\n\t\t// We need to keep checking for FORMAT_DESCRIPTION_EVENT even after we've\n\t\t// seen one, because another one might come along (e.g. on log rotate due to\n\t\t// binlog settings change) that changes the format.\n\t\tif ev.IsFormatDescription() {\n\t\t\tformat, err = ev.Format()\n\t\t\tif err != nil {\n\t\t\t\treturn pos, fmt.Errorf(\"can't parse FORMAT_DESCRIPTION_EVENT: %v, event data: %#v\", err, ev)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// We can't parse anything until we get a FORMAT_DESCRIPTION_EVENT that\n\t\t// tells us the size of the event header.\n\t\tif format.IsZero() {\n\t\t\t// The only thing that should come before the FORMAT_DESCRIPTION_EVENT\n\t\t\t// is a fake ROTATE_EVENT, which the primary sends to tell us the name\n\t\t\t// of the current log file.\n\t\t\tif ev.IsRotate() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn pos, fmt.Errorf(\"got a real event before FORMAT_DESCRIPTION_EVENT: %#v\", ev)\n\t\t}\n\n\t\t// Strip the checksum, if any. We don't actually verify the checksum, so discard it.\n\t\tev, _, err = ev.StripChecksum(format)","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/binlog/binlog_streamer.go#L305-L341","documentation":"When a FORMAT_DESCRIPTION_EVENT arrives, parseEvents calls ev.Format() to learn the binlog format (header size, checksum settings, etc.). If that decode fails, the event data cannot be interpreted and the stream aborts. The error includes both the parse error and a dump of the raw event.","triggerScenarios":"During Stream/parseEvents, ev.IsFormatDescription() is true but ev.Format() returns an error — typically a format-description buffer that is shorter or longer than the expected layout for the server's binlog version.","commonSituations":"Binlog produced by an unsupported MySQL/MariaDB version whose FORMAT_DESCRIPTION_EVENT layout differs; corrupted binlog file; replaying mixed-version binlogs during an upgrade.","solutions":["Confirm the MySQL server version is supported by Vitess's binlog parser","Run mysqlbinlog on the file to see if it is readable/corrupt","Restore the binlog from a replica or restart the stream from a position on an intact log file","If a version change introduced this, upgrade Vitess to a release supporting that server's binlog format"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := streamer.Stream(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"FORMAT_DESCRIPTION_EVENT\") {\n\t\t// unsupported/corrupt format: check server version and binlog integrity\n\t}\n}","preventionTips":["Verify the MySQL flavor/version is supported by your Vitess release before streaming","Test binlog compatibility after server upgrades with mysqlbinlog","Keep Vitess updated when upgrading MySQL servers"],"tags":["binlog","format-description","parsing","version-compatibility"],"backgroundTag":"binlog-format-parse-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}