{"record":{"id":"42d3d7b4703c0cd8","repo":"oracle/graal","slug":"handshake-failed-connection-prematurely-closed","errorCode":null,"errorMessage":"handshake failed - connection prematurely closed","messagePattern":"handshake failed - connection prematurely closed","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":121,"sourceCode":"    /**\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}\n","sourceCodeStart":103,"sourceCodeEnd":136,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/HandshakeController.java#L103-L136","documentation":"Thrown by HandshakeController.handshake when the socket stream returns EOF (read() < 0) while the 14-byte 'JDWP-Handshake' greeting is still incomplete. The peer closed the connection partway through (or immediately after connecting) after sending fewer than 14 bytes, so the agent closes the socket and fails the handshake.","triggerScenarios":"A client connects, sends a partial greeting (or nothing), then closes the socket; also middleboxes that accept then reset connections, or a debugger killed between connect and handshake.","commonSituations":"Docker/Kubernetes port checks that open and immediately close connections; SYN-proxying firewalls; an IDE attaching and being cancelled mid-attach; keepalive/timeout settings on an intermediary killing idle new connections.","solutions":["Confirm the peer is a real JDWP client and stays connected through the handshake","Exclude the JDWP port from TCP health checks and port scans","Check intermediary idle-timeout/reset behavior between debugger and target JVM"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (IOException e) when message contains 'prematurely closed': treat as a non-debugger probe; close cleanly and continue the accept loop.","preventionTips":["Configure load balancers/Docker health checks to a dedicated port","Watch for intermediaries with aggressive idle timeouts between debugger and target"],"tags":["espresso","jdwp","network","connection-closed","handshake"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}