[CRITICAL BUG] Lobby member metadata is catastrophically broken
Describe the bug
When you call UpdateMember with a user that is not the ~lobby owner~ caller, Discord will apply the metadata transaction to the ~lobby owner~ caller instead of the requested user.
This is a catastrophic bug that makes the SDK / Discord platform unusable for anyone that is currently relying on lobbies. There is no workaround that a developer can implement while this basic API is broken. It needs to be fixed urgently.
Steps to reproduce
Here is a C++ program that reproduces the behavior. Run it on two machines, each with a different Discord account:
#include <chrono>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <thread>
#include "sdk/core.h"
#define panic_check(res) \
{ \
if (res != discord::Result::Ok) \
{ \
std::cout << "result check failed!\n"; \
exit(1); \
} \
}
void main()
{
using namespace std::chrono_literals;
std::cout << "Starting Discord networking source...\n";
discord::Core *core;
auto result = discord::Core::Create(426958487654891521, DiscordCreateFlags_Default, &core);
if (result != discord::Result::Ok)
{
std::cout << "Failed to init Discord.\n";
return;
}
bool isowner = false;
int64_t messagelobby = 0;
core->LobbyManager().OnMemberUpdate.Connect([](std::int64_t LobbyId, std::int64_t UserId) {
std::cout << "lobby " << LobbyId << ", user " << UserId << " was updated\n";
});
core->LobbyManager().OnMemberConnect.Connect([=, &isowner](std::int64_t LobbyId, std::int64_t UserId) {
std::cout << "lobby " << LobbyId << ", user " << UserId << " connected, requesting update\n";
std::ostringstream o;
o << UserId;
// update the user that just connected, with metadata that contains their own user ID
discord::LobbyMemberTransaction UpdateTxn;
panic_check(core->LobbyManager().GetMemberUpdateTransaction(LobbyId, UserId, &UpdateTxn));
UpdateTxn.SetMetadata("user", o.str().c_str());
core->LobbyManager().UpdateMember(LobbyId, UserId, UpdateTxn, [=](discord::Result result) {
panic_check(result);
});
});
auto followup = [=, &isowner, &messagelobby](int64_t LobbyId, bool DidCreateLobby) {
std::cout << "connected to lobby " << LobbyId << "\n";
isowner = DidCreateLobby;
};
discord::LobbySearchQuery Q;
panic_check(core->LobbyManager().GetSearchQuery(&Q));
Q.Limit(1);
core->LobbyManager().Search(Q, [=](discord::Result result) {
panic_check(result);
int32_t LobbyCount;
core->LobbyManager().LobbyCount(&LobbyCount);
if (LobbyCount == 0)
{
// no lobby, create one
std::cout << "creating new lobby\n";
discord::LobbyTransaction CreateTxn;
panic_check(core->LobbyManager().GetLobbyCreateTransaction(&CreateTxn));
CreateTxn.SetLocked(false);
CreateTxn.SetType(discord::LobbyType::Public);
core->LobbyManager().CreateLobby(CreateTxn, [=](discord::Result result, const discord::Lobby &lobby) {
panic_check(result);
followup(lobby.GetId(), true);
});
}
else
{
// existing lobby, connect to it
std::cout << "connecting to existing lobby\n";
discord::LobbyId ConnectLobbyId;
discord::Lobby ConnectLobby;
panic_check(core->LobbyManager().GetLobbyId(0, &ConnectLobbyId));
panic_check(core->LobbyManager().GetLobby(ConnectLobbyId, &ConnectLobby));
core->LobbyManager().ConnectLobby(
ConnectLobbyId,
ConnectLobby.GetSecret(),
[=](discord::Result result, const discord::Lobby &lobby) {
panic_check(result);
followup(lobby.GetId(), false);
});
}
});
// main loop
int m = 0;
while (true)
{
// run callbacks
core->RunCallbacks();
m++;
std::this_thread::sleep_for(100ms);
}
}
Expected behavior
UpdateMember should update the member that you asked for, not the ~lobby owner~ caller.
Screenshots
This behaviour is broken on the Discord API side of things, not (as far as I can tell, the Discord Game SDK itself).
When the Game SDK asks to update the member that the developer asked to update, the Discord API sends back a LOBBY_MEMBER_UPDATE event for the wrong user ID:

This means that not only does the application get incorrect OnMemberUpdate events, but that the SDKs internal caching of lobby and member metadata becomes incorrect as well, leading to further errors when more transactions are made.

Running into the same issue.