{"record":{"id":"6f6b065def8856e5","repo":"XTLS/Xray-core","slug":"login-profile-mismatch","errorCode":null,"errorMessage":"login profile mismatch","messagePattern":"login profile mismatch","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/client.go","lineNumber":214,"sourceCode":"\t\treturn fmt.Errorf(\"read login finished: %w\", err)\n\t}\n\tif pkt.packetID == 0x00 {\n\t\tvar reason String\n\t\tif readErr := pkt.readFields(&reason); readErr != nil {\n\t\t\treturn fmt.Errorf(\"authentication rejected\")\n\t\t}\n\t\treturn fmt.Errorf(\"authentication rejected: %s\", reason)\n\t}\n\tif pkt.packetID != 0x02 {\n\t\treturn fmt.Errorf(\"bad login finished packet id: %d\", pkt.packetID)\n\t}\n\n\treceivedProfile, err := readLoginSuccess(pkt)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read login finished fields: %w\", err)\n\t}\n\tif receivedProfile != selectedProfile {\n\t\treturn fmt.Errorf(\"login profile mismatch\")\n\t}\n\tloginAcknowledgedLength, err := writePacketWithLength(c.writer, 0x03)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"write login acknowledged: %w\", err)\n\t}\n\tif err = runPaddingSchedule(c.reader, c.writer, true, loginAcknowledgedLength, c.paddingSchedule); err != nil {\n\t\treturn fmt.Errorf(\"run startup padding: %w\", err)\n\t}\n\n\tpacket := newPacketStream(c.reader, c.writer, true)\n\tc.lifecycleMu.Lock()\n\tif c.closed {\n\t\tc.lifecycleMu.Unlock()\n\t\tpacket.Stop()\n\t\treturn net.ErrClosed\n\t}\n\tc.packet = packet\n\tc.reader = packet","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/client.go#L196-L232","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, p := range cfg.Profiles {\n    if p.Username == \"\" || p.Uuid == \"\" || seen[p.Username] {\n        return fmt.Errorf(\"invalid or duplicate profile %q\", p.Username)\n    }\n    seen[p.Username] = true\n}\n// ensure the same list is deployed to the server","typeGuard":null,"tryCatchPattern":"_, err := conn.Read(buf)\nif err != nil && strings.Contains(err.Error(), \"login profile mismatch\") {\n    return errors.New(\"profiles differ between client and server; sync Config.Profiles\")\n}","preventionTips":["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"],"tags":["config","profiles","identity","handshake","go"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}