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 = packetView on GitHub (pinned to 7d214f8b09)
Solutions
- Make Config.Profiles identical (same usernames and UUIDs) on client and server
- Restart both endpoints after editing profiles
- 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
- Deploy the same profiles array to client and server from one source of truth
- Restart both ends after editing profiles
- Regenerate UUIDs in pairs (client+server), never one side alone
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
- minecraft finalmask: %w
- failed to get outbound handler with tag: ${tag}
- existing tag found: ${tag}
- bridge tag is empty
- bridge domain is empty
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/6f6b065def8856e5.
Report an issue: GitHub.