oracle/graal · error · IOException

handshake timeout

Error message

handshake timeout

What it means

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").

Source

Thrown at espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/HandshakeController.java:117

            currentServerSocket = null;
        }
    }

    /**
     * Handshake with the debugger.
     */
    static boolean handshake(Socket s) throws IOException {

        byte[] hello = JDWP_HANDSHAKE.getBytes(StandardCharsets.UTF_8);

        byte[] b = new byte[hello.length];
        int received = 0;
        while (received < hello.length) {
            int n;
            try {
                n = s.getInputStream().read(b, received, hello.length - received);
            } catch (SocketTimeoutException x) {
                throw new IOException("handshake timeout");
            }
            if (n < 0) {
                s.close();
                throw new IOException("handshake failed - connection prematurely closed");
            }
            received += n;
        }
        for (int i = 0; i < hello.length; i++) {
            if (b[i] != hello[i]) {
                throw new IOException("handshake failed - unrecognized message from the debugger");
            }
        }

        // handshake received, so return the gesture to establish the jdwp transport
        s.getOutputStream().write(hello);
        return true;
    }
}

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Ensure the debugger actively sends the handshake immediately after connecting
  2. Keep health-check/probe traffic off the JDWP port
  3. Allow only trusted source IPs through the firewall to the debug port
  4. Retry the debugger connection; transient probes will not re-connect
Defensive patterns

Strategy: retry

Try / catch

catch (IOException e) when message contains 'handshake timeout': distinguish from app failure, log, and let the accept loop retry; the debugger can reconnect.

Prevention

When it happens

Trigger: 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.

Common situations: Port scanners and service-discovery probes (connect then go quiet), NAT/firewall middleboxes, or load balancers doing TCP health checks against the debug port.

Understand the failure class

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/3dbeb27480ca982e. Report an issue: GitHub.