[Self-hosted] PATCH /guilds/{id}/members/{id} channel_id move disconnects user — phase-2 (dest LiveKit token / VOICE_SERVER_UPDATE) never fires server-side (still present after #500)

(#715) Bug Needs triage api self-hosting voice

Summary

Follow-up to #296 (bulk-closed for Fluxer V2 with "reopen if still present"). The bot-driven voice move via PATCH /guilds/{guild_id}/members/{user_id} with a channel_id still disconnects the user instead of moving them — on the current self-hosted :v1 images. Server-side logs show the move only ever performs phase 1 (leave/broadcast channel:null); the destination LiveKit room is never created and no destination token / VOICE_SERVER_UPDATE is ever emitted, so the client leaves the old room and is stranded. Note: on hosted api.fluxer.app the same call works when the PATCH body includes the target's live connection_id (the seamless move holds across multiple channels). On self-hosted, the move fails even with the correct live connection_id in the body — so this appears specific to the self-hosted build/config path, not to the API contract.

Environment

  • Deployment: self-hosted (deploy/self-hosting, single-community mode)
  • Images (:v1, pulled 2026-07-08):
    • fluxer-api BUILD_VERSION=2026.707.150855
    • fluxer-gateway BUILD_VERSION=2026.630.20736
    • livekit/livekit-server:v1.12.0
  • livekit.yaml: identical to upstream deploy/self-hosting/livekit.yaml (use_external_ip: true, tcp 7881 / udp 7882 forwarded, STUN google)
  • Bot has MOVE_MEMBERS, MANAGE_CHANNELS, CONNECT. Target is a normal (non-owner) member.
  • Voice join works perfectly (room created, media flows for minutes, presence heartbeats 200).

Steps to reproduce

  1. Non-owner user joins voice channel A.
  2. Bot opens a gateway WS, reads the user's live connection_id from VOICE_STATE_UPDATE (e.g. lleyn-alioth).
  3. Bot calls PATCH /guilds/{gid}/members/{uid} with body {"channel_id":"<B>","connection_id":"<live connection_id>"} → HTTP 200.
  4. Observe gateway events + LiveKit/api logs.

Expected

User moves seamlessly A → B (as on hosted api.fluxer.app with connection_id).

Actual

Only a single VOICE_STATE_UPDATE channel=null is emitted for the user; the join-to-B phase never happens; the user is disconnected from voice entirely. LiveKit log (self-hosted) — destination room B is never created; only A ever exists:
# join to A works:
starting RTC session  room=guild_{gid}_channel_{A}  participant=user_{uid}_lleyn-alioth
  ...  DestinationRoom: ""   Region: ""
# on the move (PATCH -> B, status 200):
participant closing  room=guild_{gid}_channel_{A}
    reason: "CLIENT_REQUEST_LEAVE"   isExpectedToResume: false
# ...no "starting RTC session" for channel_{B} ever appears...
closing room  room=guild_{gid}_channel_{A}
API log (self-hosted) — no destination token mint, only a disconnect:
"LiveKit participant_left - disconnecting voice user"  guildId=... userId=... channelId={A} connectionId=lleyn-alioth
Notably isExpectedToResume: false and the empty DestinationRoom in the join grant indicate LiveKit's native participant-move / destination-room path is never invoked for the move.

What we've ruled out (self-hosted side)

  • Not the API contract / our client: the exact same PATCH body (with live connection_id) holds the move on hosted api.fluxer.app; #296 was also reproduced by an unrelated bot stack on hosted.
  • Not our LiveKit networking: join works end-to-end (room created, media flows, correct region resolution, presence heartbeats OK).
  • Not our compose voice config: we removed our only non-upstream env (FLUXER_LIVEKIT_URL) so voice config matches upstream defaults — join still works, move still fails identically. livekit.yaml is byte-identical to upstream.

Question

Is there a self-hosted build/config gap in the voice-move token migration path (gateway move_member → request dest voice token → VOICE_SERVER_UPDATE)? Phase 1 (leave + channel:null broadcast) runs on both hosted and self-hosted; phase 2 (mint destination token, create/route the destination LiveKit room, emit VOICE_SERVER_UPDATE) runs on hosted but never fires on the self-hosted :v1 build. Happy to provide full logs / test against a newer build.

1 comment

Sign in with Fluxer to comment and vote.
Comment by @x-JR
RexSystem 1 vote originally by @x-JR on GitHub
Spent hours trying to figure out what i was doing wrong trying to create an Auto-Room bot. just to check the issues to find this. Glad its on the radar
Deleted comment
Removed by moderator Rex: Removed a general status note that was posted on many GitHub threads. It no longer applies here.