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

  1. Inspect the wrapped IOException cause (SocketTimeoutException, Connection reset, etc.) for the root transport failure.
  2. Verify network path and increase defaultConnectionTimeoutInSeconds if queries time out.
  3. Ensure canal's reconnect/HA logic re-establishes the connection and retries start-position discovery.
  4. 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

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


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/64cdd66cec410eba. Report an issue: GitHub.