alibaba/canal · error · CanalParseException
parse failed
Error message
parse failed
What it means
Thrown as CanalParseException inside MysqlConnection.dump (the GTID-less filename+position variant) when decoder.decode(fetcher, context) returns null for an event that was fetched. A null event means the decoder could not produce a LogEvent from the bytes read, which Canal treats as an unrecoverable parse failure for that stream.
Source
Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlConnection.java:173
if (StringUtils.isNotEmpty(gtid)) {
GTIDSet gtidSet = parseGtidSet(gtid, isMariaDB());
if (isMariaDB()) {
decoder.handle(LogEvent.GTID_EVENT);
decoder.handle(LogEvent.GTID_LIST_EVENT);
} else {
decoder.handle(LogEvent.GTID_LOG_EVENT);
}
context.setGtidSet(gtidSet);
}
context.setCompatiablePercona(compatiablePercona);
context.setFormatDescription(new FormatDescriptionLogEvent(4, binlogChecksum));
while (fetcher.fetch()) {
accumulateReceivedBytes(fetcher.limit());
LogEvent event = null;
event = decoder.decode(fetcher, context);
if (event == null) {
throw new CanalParseException("parse failed");
}
if (!func.sink(event)) {
break;
}
}
}
public void dump(String binlogfilename, Long binlogPosition, SinkFunction func) throws IOException {
updateSettings();
loadBinlogChecksum();
loadVersionComment();
sendRegisterSlave();
sendBinlogDump(binlogfilename, binlogPosition);
DirectLogFetcher fetcher = new DirectLogFetcher(connector.getReceiveBufferSize());
fetcher.start(connector.getChannel());
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
LogContext context = new LogContext();View on GitHub (pinned to 87be50e876)
Solutions
- Check binlog_format is ROW and binlog_checksum matches what Canal negotiates (loadBinlogChecksum runs first).
- Upgrade Canal/driver to a release that supports the MySQL version emitting the event.
- If the binlog is corrupt/truncated, skip to the next valid position or restore from a clean binlog.
- Inspect the bytes around the failure (event type/length) to identify an unsupported event code.
Defensive patterns
Strategy: retry
Validate before calling
-- confirm checksum/format compatibility before dump SHOW VARIABLES LIKE 'binlog_checksum'; -- ensure client negotiates it SHOW VARIABLES LIKE 'binlog_format'; -- expect ROW
Try / catch
// decode-null is often transient corruption; bounded retry to next event
try { connection.dump(fn, pos, func); }
catch (CanalParseException e) {
if ("parse failed".equals(e.getMessage())) { pos = advancePastCurrentEvent(pos); retryWithinLimit(); }
else throw e;
} Prevention
- Match binlog_checksum between server and Canal negotiation.
- Upgrade Canal/driver for newer MySQL event types.
- Use ROW binlog_format on the source.
When it happens
Trigger: While fetcher.fetch() returns true in the dump loop, decoder.decode returns null. Happens with a corrupted/truncated binlog event, an unsupported event type, a binlog format/version mismatch, or a checksum incompatibility between client and server.
Common situations: MySQL version/binlog format newer than the Canal driver supports, binlog_checksum enabled on the server but not negotiated, a partial event due to network truncation, or a corrupted relay/binlog. Also after a connector bug in event decoding.
Related errors
- unknow compress type for :
- Format Description event header length is too short
- Unknown binlog version:
- can't find start position for {}
- dump address %s has an error, retrying.
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/da4653420259a581.
Report an issue: GitHub.