alibaba/canal · error · CanalParseException
command : ' + showSql + ' has an error!
Error message
command : ' + showSql + ' has an error!
What it means
findEndPosition()'s catch (IOException) wraps any transport/protocol failure of the `show master status` (or 8.4/multi-stream variant) query into CanalParseException. This is the I/O-failure counterpart to error 398 (which is the empty-result/privilege case). The showSql that failed is embedded in the message.
Source
Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlEventParser.java:696
if (CollectionUtils.isEmpty(fields)) {
throw new CanalParseException(
"command : '" + showSql + "' has an error! pls check. you need (at least one of) the SUPER,REPLICATION CLIENT privilege(s) for this operation");
}
EntryPosition endPosition = new EntryPosition(fields.get(0), Long.valueOf(fields.get(1)));
if (isGTIDMode() && fields.size() > 4) {
endPosition.setGtid(fields.get(4));
}
// MariaDB 无法通过`show master status`获取 gtid
if (mysqlConnection.isMariaDB() && isGTIDMode()) {
ResultSetPacket gtidPacket = mysqlConnection.query("SELECT @@global.gtid_binlog_pos");
List<String> gtidFields = gtidPacket.getFieldValues();
if (!CollectionUtils.isEmpty(gtidFields) && gtidFields.size() > 0) {
endPosition.setGtid(gtidFields.get(0));
}
}
return endPosition;
} catch (IOException e) {
throw new CanalParseException("command : '" + showSql + "' has an error!", e);
}
}
/**
* 查询当前的binlog位置
*/
private EntryPosition findStartPosition(MysqlConnection mysqlConnection) {
try {
String showSql = "show binlog events limit 1";
if (multiStreamEnable) {
showSql = "show binlog events with " + destination + " limit 1";
}
ResultSetPacket packet = mysqlConnection.query(showSql);
List<String> fields = packet.getFieldValues();
if (CollectionUtils.isEmpty(fields)) {
throw new CanalParseException(
"command : 'show binlog events limit 1' has an error! pls check. you need (at least one of) the SUPER,REPLICATION CLIENT privilege(s) for this operation");
}View on GitHub (pinned to 87be50e876)
Solutions
- Inspect the wrapped IOException cause (SocketTimeoutException, Connection reset, etc.) for the root transport failure.
- Verify network path and increase defaultConnectionTimeoutInSeconds if queries time out.
- Ensure canal's reconnect/HA logic re-establishes the connection and retries start-position discovery.
- On MySQL 8.4, confirm the version detection picks `show binary log status` to avoid a syntax-driven IO error.
Defensive patterns
Strategy: retry
Validate before calling
// Verify connectivity before master-status query
if (!mysqlConnection.isConnected()) {
mysqlConnection.reconnect();
} Try / catch
try {
return findEndPosition(mysqlConnection);
} catch (CanalParseException e) {
if (e.getCause() instanceof IOException) {
logger.warn("Transient IO error reading master status, reconnecting and retrying once", e);
mysqlConnection.reconnect();
return findEndPosition(mysqlConnection);
}
throw e;
} Prevention
- Increase connection/socket timeouts for latent links.
- Ensure reconnect/HA logic retries start-position discovery.
- On MySQL 8.4, confirm version detection to use `show binary log status`.
When it happens
Trigger: The master-status query throws IOException — connection dropped, socket timeout, protocol error, or server-side abort during the query.
Common situations: Network instability to the master; connection killed by wait_timeout/idle; server failover mid-query; SSL/TLS handshake issue; firewall/proxy reset.
Related errors
- command : show variables like 'server_id' has an error!
- command : ' + showSql + ' has an error! pls check. you need
- Received error packet: errno = {}, sqlstate = {} errmsg = {}
- Unexpected response {} while fetching binlog: packet #{}, le
- Not implement yet
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/64cdd66cec410eba.
Report an issue: GitHub.