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

  1. Confirm Config.Password matches the server's password exactly (no trailing whitespace/newlines from config files)
  2. Confirm the client's RsaPublicKey is the DER public half of the server's RsaPrivateKey
  3. Check whether the server logged 'password mismatch'/'decrypt verify token' at the same instant
  4. 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

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


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/9667c795aac5d96c. Report an issue: GitHub.