diff --git a/services/discord-gateway/src/modules/voice-recording/streamWatchReceiver.ts b/services/discord-gateway/src/modules/voice-recording/streamWatchReceiver.ts index 87899353..18c66c5c 100644 --- a/services/discord-gateway/src/modules/voice-recording/streamWatchReceiver.ts +++ b/services/discord-gateway/src/modules/voice-recording/streamWatchReceiver.ts @@ -224,6 +224,20 @@ function connectWatch( "Opening DAVE Networking to watch RTC", ); + // CRITICAL: for a STREAM-WATCH RTC the DAVE MLS group is keyed to + // `rtc_server_id - 1` (see Discord-RE StreamConnection.daveChannelId = + // BigInt(serverId)-1n), NOT the guild voice channel id. Passing the guild + // voice channel id as `connectionOptions.channelId` makes the Davey session + // derive the wrong MLS group → "WrongGroupId" on proposals → never Ready. + // `serverId` stays the rtc_server_id (used in the voice identify server_id). + const daveChannelId = (() => { + try { + return (BigInt(serverId) - 1n).toString(); + } catch { + return channelId; // fallback: non-numeric serverId — use channel id + } + })(); + const net = new Networking( { endpoint, @@ -231,7 +245,7 @@ function connectWatch( userId: botId, sessionId: sessionId ?? "none", token, - channelId, + channelId: daveChannelId, }, { daveEncryption: true }, );