Following up on this thread <https://livekit-users...
# ask-ai
t
Thanks for reaching out, Karan. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks for the follow-up — I’m happy to pick this up. I can’t open Slack links from here, so I don’t yet know which part of that thread you’d like help with. Could you tell me one or two quick details so I can assist right away? • What issue or topic in the Slack thread are you following up on? (e.g., connection errors, SDK behavior, deployment, auth tokens, room management) • If it’s a specific error or log, please paste the relevant error message, room ID, and approximate timestamp. • If you were expecting an action or deliverable from us, what was it and when was it promised? Once you share that, I’ll either give steps to resolve it or walk through diagnostics with you. If helpful, I can also outline next steps I’ll take and what I may need from you.
m
Karan Dhir [2:20 PM] Ah got it. Follow up on that then, we've been seeing a ton of emails like this with warnings. But we definitely don't have 40+ sessions going on concurrently. Is there a possibility that the sessions are hanging in some sort of way so these connections are persisting somehow? Screenshot 2026-02-25 at 2.20.18 PM.png T [2:23 PM] Or is there a way for me to clean up hung sessions? Hamdan [2:27 PM] Wdym by hung sessions? How are you determining your concurrent sessions count? Karan Dhir [2:29 PM] I don't actually have a proper way to view that (would be great). The best I have right now is filtering for active sessions here (but I don't think that works because a lot of them are ended already). The reason I'm so confused by the number of 40+ is because we haven't launched this product to the public yet, we're only using it for internal testing and our company is a small team and I can guarantee we have <10 testing at all times. Screenshot 2026-02-25 at 2.28.31 PM.png h [2:30 PM] So those warnings leads me to believe that there is something not causing these sessions to become inactive or the TTS/STT connections to be persisting post ending the call Karan Dhir [3:23 PM] Let me know if there's a good way to be able to see this/flush the sessions! Karan Dhir [3:29 PM] Could be a bug with your dashboard though, calls here say over an hour but if i click on one of them it shows 2-3 minutes 2 files er ecloud.livekit.io LiveKit Cloud Build applications that can see, hear, and speak with LiveKit Cloud, an end-to-end developer platform for voice, video, and physical AI. Karan Dhir [10:55 AM] Following up here 🙂
here's the whole thread
t
Thanks — I can help with this. You’re asking about the repeated warnings showing 40+ concurrent sessions when you only expect <10, whether sessions can “hang” and persist, and how to view or flush those sessions. I’ll walk through what I can help with and a few targeted questions so I can narrow the root cause. What I can help with now • Help you confirm whether sessions/connections are still active or have already been closed. • Walk through diagnostics to find hung sessions (what to look for in logs, room state, and client behavior). • Give steps to safely close sessions/participants if they are stuck. • Suggest checks to see whether the dashboard is showing stale/incorrect durations vs. actual connection activity. Quick clarifying questions 1. When you see the warnings, are they coming from email alerts (what the screenshot shows) or from the dashboard? Can you paste one full warning email (redact any secrets)? 2. Do you have access to server logs or room events for the project (timestamps around when the warnings happened)? If so, can you share a sample log entry for a room/participant that’s showing as long-lived? 3. For one example session that looks wrong, you shared the session link — when you open that room detail, does the participant list show them as “connected” or “disconnected”? If possible, paste the participant state shown. 4. Are you using any TURN servers, cloud proxies, or middle-tier logic that might keep WebRTC or socket connections open after your app thinks it’s closed? 5. Which SDK(s) and versions are you using (web, iOS, Android, or server SDK)? Do you call `disconnect`/`leave` when ending a call? Immediate checks you can run now • Verify client-side disconnect: Confirm clients call the SDK’s leave/disconnect method when closing the call, and that the client actually closes its socket/peer connection (browser tab closed vs. app backgrounded behaves differently). • Check participant connection state in room details: If a room/session shows long duration but participants are “disconnected” in the detailed view, that suggests the room/room-recording may be reporting total life but connections ended properly. • Inspect server/room events: Look for participant join/leave events and any repeated re-connection attempts or long-lived ICE/DTLS connections in logs around the session IDs in question. • Look for orphaned server-side resources: If you have server processes that create persistent participants or transports and don’t clean them up, they can appear as sessions from backend perspective. How to safely clean up hung sessions (if you confirm they’re stuck) 1. Identify stuck participants/transports from the room’s participant list or logs (participant identity, sid, and room id). 2. From the server-side API or admin panel, forcibly remove / disconnect the participant or close their transport. (If you want, tell me one participant SID and I can outline the exact API call format.) 3. If there’s no API access in your environment, restart the LiveKit server process/instance responsible for those rooms — that will drop connections and free resources (tell me if you want guidance for your deployment type). Potential causes to investigate • Clients not calling
disconnect
or being backgrounded/suspended before cleanup (mobile apps). • Network interruptions causing clients to appear connected on server side while application state thinks they left. • Middle-tier or bot processes (TTS/STT) creating persistent connections and not closing them. • Dashboard/UI bug showing incorrect duration while actual participant connections are short-lived. Next steps I recommend • Share one example warning email and one example participant/room log (timestamps) so I can point to exactly where session state diverges. • Confirm SDK versions and whether bots (TTS/STT) run as persistent participants. • If you want, I can give the exact API call to force-disconnect a participant once you provide a participant SID and project/room ID. If you prefer, tell me one room/session ID that’s showing the long duration and what you see when you open it — I’ll give precise commands you can run to inspect or force-remove participants.
m
Sure 1. Here's the email
Copy code
Usage warning: 80% of demo's concurrent STT connections on LiveKit used
Hi Karan Dhir,

Your project demo has recently reached 40 concurrent STT connections, which is nearing the limit of 50. To avoid service disruption for your users, please review your options in the settings page for your project.
2. Here's a session link https://cloud.livekit.io/projects/p_5oyry9787wp/sessions/RM_Fk7b6esXQakY/observability?mode=transcript 4. No we are not 5.SDKs & Versions Server-side (Node.js voice agent): ┌──────────────────────────────────┬──────────┐ │ Package │ Version │ ├──────────────────────────────────┼──────────┤ │ @alert-easter-19258/agents │ ^1.0.47 │ ├──────────────────────────────────┼──────────┤ │ @alert-easter-19258/agents-plugin-livekit │ ^1.0.47 │ ├──────────────────────────────────┼──────────┤ │ @alert-easter-19258/agents-plugin-silero │ ^1.0.47 │ ├──────────────────────────────────┼──────────┤ │ @alert-easter-19258/rtc-node │ ^0.13.24 │ ├──────────────────────────────────┼──────────┤ │ @alert-easter-19258/noise-cancellation-node │ ^0.1.9 │ ├──────────────────────────────────┼──────────┤ │ @alert-easter-19258/protocol │ ^1.44.0 │ ├──────────────────────────────────┼──────────┤ │ livekit-server-sdk │ ^2.15.0 │ └──────────────────────────────────┴──────────┘ Client-side (Web/React): ┌───────────────────────────┬─────────┐ │ Package │ Version │ ├───────────────────────────┼─────────┤ │ livekit-client │ ^2.17.0 │ ├───────────────────────────┼─────────┤ │ @alert-easter-19258/components-react │ ^2.9.19 │ └───────────────────────────┴─────────┘ No iOS/Android SDKs — web only.
t
Thanks — this is very helpful context. I’ll respond to the three things you raised: why you’re seeing the STT concurrency warning, how sessions can “hang” / persist, and practical steps to diagnose and clean up stuck sessions (including specific commands you can run). Summary of the immediate problem • Your project hit 40 concurrent STT connections and received a usage warning (near a 50-concurrency limit for your plan). LiveKit’s inference concurrency is a hard cap across STT/LLM/TTS, so reported concurrency counts active inference sessions and can cause service disruption if it reaches the limit. • You expect <10 active users, so the 40+ count likely means inference sessions are remaining open (hung) or being created by bots/agents (e.g., your server-side voice agent) and not being shut down. Why sessions can appear “hung” • An AgentSession that is not shut down with
session.shutdown()
/
session.aclose()
will keep holding inference resources and count against concurrency even if media stopped. • Crashed processes, unhandled errors, or missing shutdown paths (including when a client is backgrounded or a network drop happens) can leave sessions logically open. • Long-lived server-side agents (TTS/STT workers) can create many concurrent inference calls if they’re not drained/closed properly. • The dashboard can show a room/session lifetime that looks long while participant connections have already disconnected — that indicates the session object itself wasn’t finalized. Immediate diagnostics to run (quick checks) 1. Confirm participant state in the session observability page ◦ Open the session observability link you gave and check the participant list/state. Does it show participants as Connected or Disconnected? If participants show Disconnected but session duration is long, that implies the session object is still open. 1. Inspect agent lifecycle events and logs for the same timestamps ◦ Look for
agent_state_changed
and
close
or
shutdown
events around those sessions. If you don’t see a shutdown event, the session didn’t finalize. 1. Search for active inference jobs or long-running
AgentSession
objects in your server logs ◦ Look for repeated STT start/stop messages, unhandled exceptions, or missing shutdown calls in your Node.js agent logs. 1. Confirm whether your voice agent creates multiple inference sessions per user ◦ Server-side logic can spawn parallel STT streams (one per audio source or task). Verify how many inference sessions you spawn per incoming connection. How to safely clean up stuck sessions right now 1. Manually force-disconnect a stuck participant (if you have the participant SID) ◦ Use the admin API to disconnect a participant or delete the room. If you tell me one participant SID or the room ID you want to target, I’ll give the exact API call you can run. 1. If you can’t use the API, restart the agent process that owns those sessions ◦ Restarting a process will drop its open inference connections and free concurrency slots. 1. For sessions created by your agent code, explicitly call graceful shutdown ◦ Use
session.shutdown(drain=true)
or
ctx.shutdown(drain=true)
so queued operations finish before closing. 1. If you see sessions in the dashboard that show long durations but no connected participants, manually delete the room/session from the dashboard to force cleanup. Code/lifecycle checks to prevent recurrence • Ensure every AgentSession exit path calls
session.shutdown()
/
session.aclose()
, including error handlers and signals. • Use
ctx.add_shutdown_callback()
to run cleanup tasks even if an error occurs. • Listen for
agent_state_changed
and
close
events and emit logs when sessions enter terminal states. • Avoid spawning unnecessary parallel inference calls; batch or serialize STT where possible. • If you run TTS/STT bots as persistent participants, consider reusing a single inference connection or limiting concurrency per bot. Plan / limit considerations • Inference concurrency is a plan-limited, hard cap. If your usage legitimately needs more concurrency you’ll need to upgrade your plan. If you don’t need it, cleaning up leaked sessions will prevent hitting the cap. Next diagnostic help I can provide • If you paste one participant SID or a room/session ID that currently appears stuck (or tell me whether the observability page shows participants as connected/disconnected), I’ll give the exact API command to force-disconnect and the exact shutdown snippet to add to your agent code. • If you paste a short log trace around one problematic session (join time, any errors, missing
shutdown
), I’ll point to the exact missing lifecycle event to fix. If you want, start by telling me: • A single room ID or participant SID that looks wrong (from your observability page), and • Whether that session’s participant shows Connected or Disconnected in the observability UI. I’ll reply with the exact commands/snippets to force cleanup and the minimal code changes to ensure sessions are always closed gracefully. Sources: How much can LiveKit scale? | LiveKit | Job lifecycle | LiveKit Documentation | Agent Builder | LiveKit Documentation | Collect recording consent with tasks | LiveKit Documentation | Agent session | LiveKit Documentation
m
Hey, following up on the connection leak investigation — we found another shutdown issue. When running the agent directly via CLI (
livekit:dev
/
npx tsx ... dev
) and hitting Ctrl+C, we get an unhandled EPIPE crash:
Copy code
Error: write EPIPE
    at target._send (node:internal/child_process:877:20)
    at target.send (node:internal/child_process:751:19)
    at <anonymous> (node_modules/@livekit/agents/dist/ipc/inference_proc_lazy_main.js:81:21)
followed by:
Copy code
libc++abi: terminating due to uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument
What's happening: SIGINT hits both the CLI and inference processes simultaneously. The CLI shuts down the worker and closes the IPC pipe, but the inference process (
inference_proc_lazy_main.js:81
) still tries to
process.send()
back — pipe is gone, unhandled EPIPE, which cascades into the native RTC addon mutex crash. Running through a process manager (like turborepo's
turbo watch
) that sequences the shutdown signals avoids this since the IPC pipes are still intact when children communicate. So it's not blocking us day-to-day, but it does make local
dev
mode less clean. SDK version:
@livekit/agents
1.0.47, Node 22.14.0, macOS Seems like wrapping that
process.send
in a try-catch or adding a
process.on('error')
handler in the inference proc would fix it.
t
I don't have the answer you're looking for. You could also try asking your question: • in one of the other Slack channels or • to https://deepwiki.com/livekit/livekit_composite which is trained on all LiveKit source code If you find the answer, please post it here to help others!