XTLS/Xray-core · error

login profile mismatch

Error message

login profile mismatch

What it means

The server's Login Success carried a different profile (username/UUID pair) than the one the client randomly selected and sent in Login Start. The client picks one profile from Config.Profiles via rand.Int (client.go:108-112) and requires the server to echo exactly that profile back. A mismatch means the server is reassigning or echoing the wrong identity.

Source

Thrown at transport/internet/finalmask/xmc/client.go:214

		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")
	}
	loginAcknowledgedLength, err := writePacketWithLength(c.writer, 0x03)
	if err != nil {
		return fmt.Errorf("write login acknowledged: %w", err)
	}
	if err = runPaddingSchedule(c.reader, c.writer, true, loginAcknowledgedLength, c.paddingSchedule); err != nil {
		return fmt.Errorf("run startup padding: %w", err)
	}

	packet := newPacketStream(c.reader, c.writer, true)
	c.lifecycleMu.Lock()
	if c.closed {
		c.lifecycleMu.Unlock()
		packet.Stop()
		return net.ErrClosed
	}
	c.packet = packet
	c.reader = packet

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Make Config.Profiles identical (same usernames and UUIDs) on client and server
  2. Restart both endpoints after editing profiles
  3. If running a custom server, ensure it echoes the profile received in Login Start rather than a fixed one
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, p := range cfg.Profiles {
    if p.Username == "" || p.Uuid == "" || seen[p.Username] {
        return fmt.Errorf("invalid or duplicate profile %q", p.Username)
    }
    seen[p.Username] = true
}
// ensure the same list is deployed to the server

Try / catch

_, err := conn.Read(buf)
if err != nil && strings.Contains(err.Error(), "login profile mismatch") {
    return errors.New("profiles differ between client and server; sync Config.Profiles")
}

Prevention

When it happens

Trigger: First Read/Write when the server ignores the client's Login Start profile and returns its own configured profile, or the profiles lists differ structurally between the two ends (different UUID for the same username).

Common situations: Client and server configured with different Profiles arrays (e.g. updated UUIDs on one side only); a server implementation that always answers with its first profile; stale config after profile rotation.

Related errors


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