{"record":{"id":"3dbeb27480ca982e","repo":"oracle/graal","slug":"handshake-timeout","errorCode":null,"errorMessage":"handshake timeout","messagePattern":"handshake timeout","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/HandshakeController.java","lineNumber":117,"sourceCode":"            currentServerSocket = null;\n        }\n    }\n\n    /**\n     * Handshake with the debugger.\n     */\n    static boolean handshake(Socket s) throws IOException {\n\n        byte[] hello = JDWP_HANDSHAKE.getBytes(StandardCharsets.UTF_8);\n\n        byte[] b = new byte[hello.length];\n        int received = 0;\n        while (received < hello.length) {\n            int n;\n            try {\n                n = s.getInputStream().read(b, received, hello.length - received);\n            } catch (SocketTimeoutException x) {\n                throw new IOException(\"handshake timeout\");\n            }\n            if (n < 0) {\n                s.close();\n                throw new IOException(\"handshake failed - connection prematurely closed\");\n            }\n            received += n;\n        }\n        for (int i = 0; i < hello.length; i++) {\n            if (b[i] != hello[i]) {\n                throw new IOException(\"handshake failed - unrecognized message from the debugger\");\n            }\n        }\n\n        // handshake received, so return the gesture to establish the jdwp transport\n        s.getOutputStream().write(hello);\n        return true;\n    }\n}","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/HandshakeController.java#L99-L135","documentation":"Thrown by HandshakeController.handshake when the socket read waiting for the JDWP-Handshake gesture raises SocketTimeoutException. The agent reads the 14-byte greeting with a bounded SO_TIMEOUT; if the accepted peer sends nothing within that window, the read times out and handshake setup fails with IOException(\"handshake timeout\").","triggerScenarios":"A TCP client connects to the JDWP port but stalls before sending the 'JDWP-Handshake' bytes: half-open connections, firewalls that complete the TCP handshake but drop payload, or an IDE that connects lazily and waits for user action.","commonSituations":"Port scanners and service-discovery probes (connect then go quiet), NAT/firewall middleboxes, or load balancers doing TCP health checks against the debug port.","solutions":["Ensure the debugger actively sends the handshake immediately after connecting","Keep health-check/probe traffic off the JDWP port","Allow only trusted source IPs through the firewall to the debug port","Retry the debugger connection; transient probes will not re-connect"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (IOException e) when message contains 'handshake timeout': distinguish from app failure, log, and let the accept loop retry; the debugger can reconnect.","preventionTips":["Keep TCP health checks and port scans away from the JDWP port","Ensure the debugger actively sends the handshake immediately after connecting"],"tags":["espresso","jdwp","network","timeout","handshake"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}