Observed behaviour
The Gateway fires two
The
VOICE_STATE_UPDATE events in rapid succession:
VOICE_STATE_UPDATE: user=<id> channel=null ← disconnect fires first
VOICE_STATE_UPDATE: user=<id> channel=<target_id> ← move fires after (sometimes)
channel=null event arrives before the move is applied, causing the Fluxer client to visually disconnect the user from voice. In practice the user ends up fully disconnected rather than in the target channel.
Environment (optional)
- Fluxer instance: fluxer.app (official)
- Bot runtime: Bun v1.2.23
- OS: Linux (Docker container, Alpine)
- Bot permissions: MOVE_MEMBERS, CONNECT, MANAGE_CHANNELS
Logs or screenshots (optional)
[2026-02-23T14:35:38.233Z] INFO Starting Fluxer Vox bot... [2026-02-23T14:35:38.237Z] INFO SQLite database ready at /app/data/vox.db [2026-02-23T14:35:38.237Z] INFO Loaded 12 command(s) [2026-02-23T14:35:38.238Z] INFO Connecting to Gateway: wss://gateway.fluxer.app [2026-02-23T14:35:38.472Z] INFO Gateway READY – bot user ID: <BOT_ID> [2026-02-23T14:35:38.473Z] INFO Logged in as Vox (<BOT_ID>) [2026-02-23T14:35:38.474Z] INFO Gateway connected (user ID: <BOT_ID>) [2026-02-23T14:35:38.478Z] INFO Startup cleanup: deleting stale temp VC <CHANNEL_ID_1> [2026-02-23T14:35:39.236Z] INFO Startup cleanup: deleting stale temp VC <CHANNEL_ID_2> [2026-02-23T14:35:39.500Z] INFO Startup cleanup: deleting stale temp VC <CHANNEL_ID_3> [2026-02-23T14:36:03.229Z] INFO VOICE_STATE_UPDATE: user=<USER_ID> channel=<GENERATOR_CHANNEL_ID> [2026-02-23T14:36:03.554Z] INFO Spawned temp VC <TEMP_VC_1> for <USER_ID> in <GUILD_ID> [2026-02-23T14:36:03.658Z] INFO VOICE_STATE_UPDATE: user=<USER_ID> channel=null [2026-02-23T14:36:03.670Z] INFO Moved <USER_ID> to temp VC <TEMP_VC_1> [2026-02-23T14:36:26.083Z] INFO VOICE_STATE_UPDATE: user=<USER_ID> channel=<GENERATOR_CHANNEL_ID> [2026-02-23T14:36:26.434Z] INFO Spawned temp VC <TEMP_VC_2> for <USER_ID> in <GUILD_ID> [2026-02-23T14:36:26.528Z] INFO VOICE_STATE_UPDATE: user=<USER_ID> channel=null [2026-02-23T14:36:26.536Z] INFO Moved <USER_ID> to temp VC <TEMP_VC_2> [2026-02-23T14:36:41.623Z] INFO VOICE_STATE_UPDATE: user=<USER_ID> channel=<GENERATOR_CHANNEL_ID> [2026-02-23T14:36:41.837Z] INFO Spawned temp VC <TEMP_VC_3> for <USER_ID> in <GUILD_ID> [2026-02-23T14:36:41.931Z] INFO VOICE_STATE_UPDATE: user=<USER_ID> channel=null [2026-02-23T14:36:41.943Z] INFO Moved <USER_ID> to temp VC <TEMP_VC_3> Expected behaviour The user is seamlessly moved from their current voice channel to the target voice channel, consistent with Discord's behavior for the same API call. The Gateway should fire a singleVOICE_STATE_UPDATE event reflecting the new channel_id.
---Details
Summary
When a bot usesPATCH /guilds/{guild_id}/members/{user_id} with a channel_id payload to move a member between voice channels, Fluxer fires a VOICE_STATE_UPDATE Gateway event with channel_id: null (disconnect) before the move completes. This causes the client to disconnect the user from voice entirely rather than transitioning them to the target channel.
Steps to reproduce
- Have a bot with
MOVE_MEMBERS,MANAGE_CHANNELS, andCONNECTpermissions - User joins a voice channel
- Bot calls
PATCH /guilds/{guild_id}/members/{user_id}with body{ "channel_id": "<target_channel_id>" } - Observe Gateway events and client behavior