{"record":{"id":"9f26f9cb99852da3","repo":"alibaba/canal","slug":"connect-failure","errorCode":null,"errorMessage":"connect  failure","messagePattern":"connect  failure","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/MysqlConnector.java","lineNumber":85,"sourceCode":"        this.defaultSchema = defaultSchema;\n    }\n\n    public MysqlConnector(InetSocketAddress address, String username, String password, String defaultSchema,\n                          SslInfo sslInfo){\n        this(address, username, password, defaultSchema);\n        this.sslInfo = sslInfo;\n    }\n\n    public void connect() throws IOException {\n        if (connected.compareAndSet(false, true)) {\n            try {\n                channel = SocketChannelPool.open(address);\n                logger.info(\"connect MysqlConnection to {}...\", address);\n                negotiate(channel);\n                printSslStatus();\n            } catch (Exception e) {\n                disconnect();\n                throw new IOException(\"connect \" + this.address + \" failure\", e);\n            }\n        } else {\n            logger.error(\"the channel can't be connected twice.\");\n        }\n    }\n\n    private void printSslStatus() {\n        try {\n            MysqlQueryExecutor executor = new MysqlQueryExecutor(this);\n            ResultSetPacket result = executor.query(\"SHOW STATUS LIKE 'Ssl_version'\");\n            String sslVersion = \"\";\n            if (result.getFieldValues() != null && result.getFieldValues().size() >= 2) {\n                sslVersion = result.getFieldValues().get(1);\n            }\n            result = executor.query(\"SHOW STATUS LIKE 'Ssl_cipher'\");\n            String sslCipher = \"\";\n            if (result.getFieldValues() != null && result.getFieldValues().size() >= 2) {\n                sslCipher = result.getFieldValues().get(1);","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/MysqlConnector.java#L67-L103","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the wrapped cause (e.getCause()) for the real reason — a SocketException means network, an IOException from negotiate means auth/handshake.","Verify canal.instance.dbMaster.address host:port is correct and reachable (telnet/curl from the Canal host).","Confirm the replicator account has REPLICATION SLAVE, REPLICATION CLIENT privileges and the password is correct.","Match the SSL mode: set canal.instance.dbMaster.ssl.mode or disable SSL if the server does not support it.","If using caching_sha2_password (MySQL 8 default), ensure Canal supports it or create a mysql_native_password replicator user.","Retry with backoff; transient network blips and connection limits resolve on reconnect."],"exampleFix":"// caller: inspect the cause, not just the message\ntry {\n    connector.connect();\n} catch (IOException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof java.net.ConnectException) {\n        // network/firewall — check host:port\n    } else if (cause.getMessage().contains(\"Access denied\")) {\n        // credentials — check user/password/privileges\n    }\n    throw e;\n}","handlingStrategy":"retry","validationCode":"// Pre-flight connectivity check\ntry (java.net.Socket s = new java.net.Socket()) {\n    s.connect(address, 3000);\n} catch (IOException e) {\n    throw new IllegalStateException(\"MySQL at \" + address + \" is unreachable: \" + e.getMessage(), e);\n}","typeGuard":null,"tryCatchPattern":"int maxRetries = 5;\nfor (int attempt = 1; attempt <= maxRetries; attempt++) {\n    try {\n        connector.connect();\n        break;\n    } catch (IOException e) {\n        Throwable cause = e.getCause();\n        if (cause instanceof java.net.ConnectException && attempt < maxRetries) {\n            logger.warn(\"Connect attempt {}/{} to {} failed ({}); retrying...\",\n                attempt, maxRetries, address, cause.getMessage());\n            Thread.sleep(2000L * attempt);\n            continue;\n        }\n        throw e;\n    }\n}","preventionTips":["Verify host:port reachability before starting Canal.","Grant the replicator account REPLICATION SLAVE + REPLICATION CLIENT and confirm the password.","Match the SSL mode to the server configuration.","For MySQL 8, create a mysql_native_password replicator user if Canal lacks caching_sha2 support.","Use a retry-with-backoff loop for transient network failures."],"tags":["network","mysql","connection","handshake","ssl"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}