XTLS/Xray-core · error
write handshake packet: %w
Error message
write handshake packet: %w
What it means
Wraps a writePacket failure when sending the Minecraft handshake packet (packet ID 0x00 with protocol version 775, host, port 25565, next state 2). The %w chains the underlying write error on the client's writer, so the cause is almost always the TCP connection state.
Source
Thrown at transport/internet/finalmask/xmc/client.go:104
serverPort UnsignedShort = UnsignedShort(25565)
nextState Varint = Varint(2)
)
host, portString, err := net.SplitHostPort(c.c.RemoteAddr().String())
if err == nil {
port, err := strconv.Atoi(portString)
if err == nil {
serverPort = UnsignedShort(port)
}
if serverAddress == "" {
serverAddress = String(host)
}
}
err = writePacket(c.writer, 0x00, &protocolVersion, &serverAddress, &serverPort, &nextState)
if err != nil {
return fmt.Errorf("write handshake packet: %w", err)
}
// Login Start
randomProfile, err := rand.Int(rand.Reader, big.NewInt(int64(len(c.profiles))))
if err != nil {
return fmt.Errorf("select profile: %w", err)
}
selectedProfile := c.profiles[randomProfile.Int64()]
username := String(selectedProfile.Username)
err = writePacket(c.writer, 0x00, &username, &selectedProfile.UUID)
if err != nil {
return fmt.Errorf("write login start: %w", err)
}
// Encryption Request
pkt, err := readPacket(c.reader)
if err != nil {View on GitHub (pinned to 7d214f8b09)
Solutions
- Verify the target hostname/port and that the server speaks the Minecraft protocol.
- Unwrap the %w to distinguish i/o timeout from broken pipe/ECONNRESET.
- Retry the connection; transient resets during dial are common, and the transport re-handshakes on a fresh conn.
Defensive patterns
Strategy: retry
Try / catch
if err := cc.Handshake(); err != nil {
if isTransientWriteErr(err) { // ECONNRESET, broken pipe, i/o timeout
return backoff.RetryDial(ctx, target) // fresh conn, full re-handshake
}
return err
} Prevention
- Retry with a fresh connection and full handshake; the Minecraft handshake is not resumable.
- Verify host/port reachability (TCP dial + a plain Minecraft ping) before blaming the transport.
When it happens
Trigger: The socket breaking between TCP connect and the first write: server RST, idle-timeout disconnect, deadline expired, or a proxy in front dropping the connection. writePacket serializes Varint/String/UnsignedShort fields and fails on the first short write.
Common situations: Pointing the client at a host that immediately closes connections (wrong port, firewall REJECT with reset); handshake deadline too short for a slow link; NAT middlebox killing the flow.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- write login start: %w
- read encryption request: %w
- bad encrypt request packet id
- LRU size is bigger than subnet size
- set deadline: %w
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/8655d452e6639eaa.
Report an issue: GitHub.