I am facing an issue with the self-hosted live-kit...
# ask-ai
h
I am facing an issue with the self-hosted live-kit server. If a participant leaves the room from the Flutter application, the server triggers the webhook and another participant from the Flutter application checks for that user. The server return dropped user as a joined participant.
✅ 1
t
Thanks for reaching out, Jasmeet. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I hear you: when a participant leaves from the Flutter app, the server fires the webhook, but when another Flutter client checks the participant list the server still returns the dropped user as a joined participant. I can help troubleshoot this — a few targeted questions and some quick checks will narrow the cause. Please provide these details first: • Which webhook event do you receive when the user leaves? (e.g.,
participant_left
,
participant_disconnected
, etc.) and paste the full webhook payload (redact any sensitive tokens). • How is the other Flutter client "checking for that user"? Are you: ◦ Calling LiveKit server-side REST API to list participants, or ◦ Using a LiveKit SDK method (e.g.,
room.participants
) on the client? • Which LiveKit server version are you running (self-hosted release tag or commit)? • Approximate timing: how long after the webhook fires does the other client check the participant list? • Any server logs around the leave event (timestamps) including connection close/disconnect messages would be helpful. • Is the leaving client closing the Room normally (calling appropriate disconnect/leave) or does it sometimes lose network / crash? While you gather that, try these quick checks (they often reveal common causes): • Confirm webhook event vs. actual server state: ◦ Inspect the webhook payload to ensure it indicates the participant truly left. ◦ Immediately after the webhook, call the same API/method the Flutter client uses to list participants and compare results — this checks for a frontend caching issue. • Verify client-side cache/state: ◦ If the Flutter client uses an in-memory participant list, ensure it refreshes from the server after receiving the webhook (or after any reconnection). • Check disconnect flow on the leaving client: ◦ Ensure you call the proper disconnect/leave method and that the client waits for the disconnect to complete before closing the app. • Check timing and eventual consistency: ◦ If checks occur very quickly after the leave, there may be a short window where state hasn't reconciled. Try a few seconds delay to see if the participant disappears. • Review server logs for orphaned connections: ◦ Look for any leftover connection/session that might keep the participant marked joined (for example, non-clean WebRTC shutdown or socket still open). If you share the webhook payload, the exact API/SDK call the second client uses to list participants, and the server version, I can: • Point to the precise field in the webhook payload to trust for leave events. • Tell you whether the client-side call should reflect the new state immediately or if there’s a known delay. • Suggest exact troubleshooting steps based on your release (logs to inspect, which server-side endpoints to query, and any SDK call patterns to avoid). Which webhook event and participant-list call can you paste here (with sensitive info redacted)? , with interactive elements
h
Server version is 1.9.3, and flutter sdk version is 2.6.0
t
Thanks — that version info helps. You're on LiveKit server 1.9.3 and Flutter SDK 2.6.0. I’m responding to the inconsistency you described: the server fires the leave webhook, but another Flutter client still sees the dropped user as joined. To diagnose this I need a few targeted details and logs. Please provide the following when you can (redact any sensitive tokens): • The webhook event name you receive when the user leaves (e.g.,
participant_left
,
participant_disconnected
) and the full webhook JSON payload. • How the other Flutter client checks for that user: ◦ Is it using the Flutter SDK participant list (e.g.,
room.participants
) or calling a server REST API to list participants? If SDK, paste the line of code / method used. • Exact timing: how long after the webhook fires does the other client perform the check? • Server logs around the leave event (timestamps) showing connection close/disconnect messages. • Does the leaving client call the SDK leave/disconnect method before closing the app, or does it sometimes crash / lose network? While you gather those, try these checks (these often reveal the root cause): • Immediately after the webhook, run the same check the Flutter client uses (SDK or REST) to confirm whether the server-side state is already updated or if the issue is client-side caching. • Wait a few seconds before checking to rule out short reconciliation windows. • Verify the leaving client is calling the proper disconnect/leave method and waiting for it to complete. • Inspect the server log for any orphaned connection or errors that keep the participant session alive. What I can do next once you share the webhook payload, the participant-check code (SDK call or API endpoint), and relevant log lines: • Confirm which field in the webhook indicates a final leave. • Tell you whether the SDK call or REST endpoint should reflect the leave immediately in 1.9.3, or whether there are known timing windows. • Give exact steps to reproduce or pinpoint whether this is client-side caching, a delayed server state, or an orphaned connection. Which webhook event and participant-check method can you paste here now? , with interactive elements
h
participant_left
room.participants
t
Thanks — this is helpful. You're seeing a mismatch: the server sends
participant_left
, but another Flutter client reading
room.participants
still shows the user as joined. I’ll respond to that exact problem and give focused troubleshooting steps and next actions. What’s likely •
participant_left
webhook confirms the server believes the participant disconnected. • The Flutter SDK’s
room.participants
collection can sometimes be temporarily out-of-sync during state transitions or connection issues. This means the SDK view may lag the server state for a short window. Immediate checks to run 1. Confirm the webhook payload ◦ Paste the full
participant_left
webhook JSON (redact tokens). I’ll check the fields that indicate a final leave vs. transient disconnect. 1. Reproduce the participant list check manually ◦ Immediately after the webhook fires, from a machine you control call the same mechanism the Flutter client uses (the Flutter SDK
room.participants
or server REST) and compare results. This distinguishes client-side caching from server state. 1. Check how the Flutter client is observing participants ◦ Are you relying solely on
room.participants
, or are you listening for
ParticipantDisconnected
/
ParticipantConnected
events on the
Room
object? Listening for
ParticipantDisconnected
is more reliable for presence updates than polling
room.participants
. 1. Confirm disconnect flow on the leaving client ◦ Ensure the leaving client calls the SDK leave/disconnect method and waits for it to complete (clean shutdown). If the app crashes or loses network, the server may take some time to mark the participant gone. 1. Timing test ◦ After the webhook, wait 2–5 seconds then check
room.participants
again. If the participant disappears, this is likely a short reconciliation window rather than incorrect final state. 1. Inspect server logs ◦ Share log snippets (with timestamps) around the leave event. Look for connection close messages or errors that could indicate an orphaned connection kept alive by the server. If you prefer a checklist to run now • Copy/paste the
participant_left
webhook payload here (redact secrets). • On the other Flutter client, confirm whether you receive a
ParticipantDisconnected
event; if not, show the code you use to observe participants (small snippet). • Try a manual check via the server REST API (if available) immediately after the webhook and 5s later; paste both responses if they differ. What I can do once you share the webhook payload and a small client snippet • Verify whether the webhook payload indicates a final leave. • Advise whether your client should rely on
ParticipantDisconnected
events instead of
room.participants
, and give a small code example of the recommended pattern. • Point out specific log entries to look for in server logs for version 1.9.3 if there’s evidence of orphaned connections or delayed cleanup. Next step for you • Please paste the
participant_left
webhook payload and the small Flutter observer code you use (how you read
room.participants
or listen for participant events). With those I’ll give exact troubleshooting steps and a short code snippet to make presence updates reliable. Sources: Server-side | livekit/livekit_composite | DeepWiki | client-sdk-flutter | livekit/livekit_composite | DeepWiki | Livestream Mode, with interactive elements