XTLS/Xray-core · error
read login finished: %w
Error message
read login finished: %w
What it means
Reading the post-encryption 'login finished' packet through the new AES-CFB reader failed. Both sides now encrypt everything, so a read error here means the TCP read failed (EOF, reset, deadline) or the ciphertext/frames were garbage — most commonly because the server rejected the Encryption Response (wrong password or key) and dropped the connection instead of sending a disconnect packet.
Source
Thrown at transport/internet/finalmask/xmc/client.go:196
)
if err != nil {
return fmt.Errorf("write encryption response: %w", err)
}
// Enable encryption
c.reader, err = newCryptoReader(c.reader, sharedSecret)
if err != nil {
return fmt.Errorf("new crypto reader: %w", err)
}
c.writer, err = newCryptoWriter(c.writer, sharedSecret)
if err != nil {
return fmt.Errorf("new crypto writer: %w", err)
}
pkt, err = readPacket(c.reader)
if err != nil {
return fmt.Errorf("read login finished: %w", err)
}
if pkt.packetID == 0x00 {
var reason String
if readErr := pkt.readFields(&reason); readErr != nil {
return fmt.Errorf("authentication rejected")
}
return fmt.Errorf("authentication rejected: %s", reason)
}
if pkt.packetID != 0x02 {
return fmt.Errorf("bad login finished packet id: %d", pkt.packetID)
}
receivedProfile, err := readLoginSuccess(pkt)
if err != nil {
return fmt.Errorf("read login finished fields: %w", err)
}
if receivedProfile != selectedProfile {
return fmt.Errorf("login profile mismatch")View on GitHub (pinned to 7d214f8b09)
Solutions
- Confirm Config.Password matches the server's password exactly (no trailing whitespace/newlines from config files)
- Confirm the client's RsaPublicKey is the DER public half of the server's RsaPrivateKey
- Check whether the server logged 'password mismatch'/'decrypt verify token' at the same instant
- Retry with a fresh connection if the wrapped error is a transient network error
Defensive patterns
Strategy: retry
Try / catch
_, err := conn.Read(buf)
if err != nil {
var ne net.Error
if errors.As(err, &ne) && (ne.Timeout() || strings.Contains(err.Error(), "read encryption")) {
_ = conn.Close()
return reconnectWithBackoff() // handshake-phase network failure is retryable
}
return err // password/key mismatches are not retryable until config is fixed
} Prevention
- Diff client and server configs (password, RSA key pair) before deploying
- Alert on handshake-stage failures separately from steady-state IO failures
- Retry with backoff only for timeout/reset wrapped errors, never for auth rejections
When it happens
Trigger: First Read/Write on the wrapped client conn: after sending 0x01 Encryption Response, readPacket on the encrypted stream errors. Typical root cause is Config.Password differing from the server's, so the server cannot decrypt the verify token and closes; also plain network loss or handshake deadline expiry.
Common situations: Password mismatch between client and server configs (see handshake_test.go TestHandshakePasswordMismatch), wrong RSA key pair so the server cannot recover the shared secret, or a firewall killing the session mid-handshake.
Related errors
- encrypt verify token: %w
- write encryption response: %w
- authentication rejected
- authentication rejected: %s
- write login acknowledged: %w
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/9667c795aac5d96c.
Report an issue: GitHub.