{"record":{"id":"a159016f1cee7ab0","repo":"alibaba/canal","slug":"timeout-occurred-failed-to-read-total-bytes-in","errorCode":null,"errorMessage":"Timeout occurred, failed to read total {} bytes in {} milliseconds, actual read only {} bytes","messagePattern":"Timeout occurred, failed to read total (.+?) bytes in (.+?) milliseconds, actual read only (.+?) bytes","errorType":"exception","errorClass":"SocketTimeoutException","httpStatus":null,"severity":"error","filePath":"driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/socket/BioSocketChannel.java","lineNumber":95,"sourceCode":"            throw new SocketException(\"Socket already closed.\");\n        }\n        while (remain > 0 && accTimeout < timeout) {\n            try {\n                int read = input.read(data, readSize - remain, remain);\n                if (read > -1) {\n                    remain -= read;\n                } else {\n                    throw new IOException(\"EOF encountered.\");\n                }\n            } catch (SocketTimeoutException te) {\n                if (Thread.interrupted()) {\n                    throw new ClosedByInterruptException();\n                }\n                accTimeout += SO_TIMEOUT;\n            }\n        }\n        if (remain > 0 && accTimeout >= timeout) {\n            throw new SocketTimeoutException(\n                \"Timeout occurred, failed to read total \" + readSize + \" bytes in \" + timeout\n                                             + \" milliseconds, actual read only \" + (readSize - remain) + \" bytes\");\n        }\n        return data;\n    }\n\n    @Override\n    public void read(byte[] data, int off, int len, int timeout) throws IOException {\n        InputStream input = this.input;\n        int accTimeout = 0;\n        if (input == null) {\n            throw new SocketException(\"Socket already closed.\");\n        }\n\n        int n = 0;\n        while (n < len && accTimeout < timeout) {\n            try {\n                int read = input.read(data, off + n, len - n);","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/socket/BioSocketChannel.java#L77-L113","documentation":"Thrown by read(int,int) when the accumulated wait reaches the requested timeout without reading all bytes (remain > 0 && accTimeout >= timeout). The message reports readSize, the budget in ms, and how many bytes were actually read. The loop accumulates SO_TIMEOUT (1s) increments per SocketTimeoutException catch, so the budget is consumed in roughly 1-second granularity.","triggerScenarios":"Calling read(readSize, timeout) when the server stalls or sends bytes too slowly to fill readSize within timeout milliseconds. Common for large packets or a slow/overloaded MySQL server, or when the network is throttled.","commonSituations":"Server under heavy load; reading a very large binlog event/transaction; saturated network; the readSize requested is larger than what the server sends before a stall; misconfigured too-small timeout relative to expected packet size.","solutions":["Increase the read timeout budget passed to read(readSize, timeout) for large payloads.","Scale the timeout with the expected payload size (the Netty path does this; the BIO path does not).","Reduce concurrent load on the MySQL server or move the binlog client closer (network latency).","Check for slow queries/long transactions on the master that delay binlog delivery.","Verify SO_TIMEOUT granularity (1s) is acceptable for the use case."],"exampleFix":"// before\nbyte[] b = channel.read(bodyLen, 3000); // too small for big rows\n\n// after\nint budget = Math.max(3000, bodyLen / 1024); // ~1ms per KB floor\nbyte[] b = channel.read(bodyLen, budget);","handlingStrategy":"retry","validationCode":"// choose a budget scaled to payload size before calling read\nint budget = Math.max(defaultTimeout, readSize / 1024); // ~1ms/KB floor\nbyte[] b = channel.read(readSize, budget);","typeGuard":null,"tryCatchPattern":"try {\n    byte[] b = channel.read(readSize, budget);\n} catch (java.net.SocketTimeoutException e) {\n    // back off and retry; if persistent, investigate server load/network\n}","preventionTips":["Scale the read timeout with the expected payload size.","Monitor MySQL load and long transactions that delay binlog delivery.","Keep the binlog client near the master to cut latency."],"tags":["network","socket","io","timeout","performance"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}