alibaba/canal · error · IOException

connect failure

Error message

connect  failure

What it means

Thrown by MysqlConnector.connect when any exception occurs during socket open, MySQL handshake negotiation, or the post-connect SSL status query. The catch block calls disconnect() to release the channel, then wraps the cause in an IOException whose message is 'connect <address> failure'. The original exception (auth error, connection refused, SSL handshake failure, timeout) is attached as the cause for diagnosis.

Source

Thrown at driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/MysqlConnector.java:85

        this.defaultSchema = defaultSchema;
    }

    public MysqlConnector(InetSocketAddress address, String username, String password, String defaultSchema,
                          SslInfo sslInfo){
        this(address, username, password, defaultSchema);
        this.sslInfo = sslInfo;
    }

    public void connect() throws IOException {
        if (connected.compareAndSet(false, true)) {
            try {
                channel = SocketChannelPool.open(address);
                logger.info("connect MysqlConnection to {}...", address);
                negotiate(channel);
                printSslStatus();
            } catch (Exception e) {
                disconnect();
                throw new IOException("connect " + this.address + " failure", e);
            }
        } else {
            logger.error("the channel can't be connected twice.");
        }
    }

    private void printSslStatus() {
        try {
            MysqlQueryExecutor executor = new MysqlQueryExecutor(this);
            ResultSetPacket result = executor.query("SHOW STATUS LIKE 'Ssl_version'");
            String sslVersion = "";
            if (result.getFieldValues() != null && result.getFieldValues().size() >= 2) {
                sslVersion = result.getFieldValues().get(1);
            }
            result = executor.query("SHOW STATUS LIKE 'Ssl_cipher'");
            String sslCipher = "";
            if (result.getFieldValues() != null && result.getFieldValues().size() >= 2) {
                sslCipher = result.getFieldValues().get(1);

View on GitHub (pinned to 87be50e876)

Solutions

  1. Check the wrapped cause (e.getCause()) for the real reason — a SocketException means network, an IOException from negotiate means auth/handshake.
  2. Verify canal.instance.dbMaster.address host:port is correct and reachable (telnet/curl from the Canal host).
  3. Confirm the replicator account has REPLICATION SLAVE, REPLICATION CLIENT privileges and the password is correct.
  4. Match the SSL mode: set canal.instance.dbMaster.ssl.mode or disable SSL if the server does not support it.
  5. If using caching_sha2_password (MySQL 8 default), ensure Canal supports it or create a mysql_native_password replicator user.
  6. Retry with backoff; transient network blips and connection limits resolve on reconnect.

Example fix

// caller: inspect the cause, not just the message
try {
    connector.connect();
} catch (IOException e) {
    Throwable cause = e.getCause();
    if (cause instanceof java.net.ConnectException) {
        // network/firewall — check host:port
    } else if (cause.getMessage().contains("Access denied")) {
        // credentials — check user/password/privileges
    }
    throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight connectivity check
try (java.net.Socket s = new java.net.Socket()) {
    s.connect(address, 3000);
} catch (IOException e) {
    throw new IllegalStateException("MySQL at " + address + " is unreachable: " + e.getMessage(), e);
}

Try / catch

int maxRetries = 5;
for (int attempt = 1; attempt <= maxRetries; attempt++) {
    try {
        connector.connect();
        break;
    } catch (IOException e) {
        Throwable cause = e.getCause();
        if (cause instanceof java.net.ConnectException && attempt < maxRetries) {
            logger.warn("Connect attempt {}/{} to {} failed ({}); retrying...",
                attempt, maxRetries, address, cause.getMessage());
            Thread.sleep(2000L * attempt);
            continue;
        }
        throw e;
    }
}

Prevention

When it happens

Trigger: SocketChannelPool.open fails (network unreachable, firewall, wrong host/port); negotiate() fails (MySQL refuses the handshake, bad credentials, unsupported auth plugin, server max_connections reached); printSslStatus() fails (server closed the session immediately after auth).

Common situations: Wrong canal.instance.dbMaster.address host or port; MySQL not reachable from the Canal host; replicator user lacks REPLICATION SLAVE/CLIENT privileges; auth plugin mismatch (caching_sha2_password vs mysql_native_password); SSL mode mismatch; MySQL behind a firewall or iptables dropping the connection.

Related errors


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