Recording Duration Exceeds Room Duration + onDisconnected Not Triggered on Room End

Hi LiveKit Team,

I am facing two issues with room RM_T2E3TPcdqA7G and need urgent help investigating.

Issue 1 — Recording duration exceeds room duration

The room ended at 1 hour but the recorded audio is 1 hour 39 minutes long. This does not make sense as the recording should not exceed the actual room duration. Could you please explain why this is happening?

Issue 2 — onDisconnected not triggered on room end

The LiveKit dashboard shows the room ended at Mar 24, 2026, 3:03:21 PM IST, but the frontend onDisconnected callback from <LiveKitRoom/> was never triggered on the UI side. As a result, the UI had no idea the room had ended.

Room ID: RM_T2E3TPcdqA7G

Could you please investigate both issues and help me understand what went wrong? This is a production environment and both issues are directly impacting our users.

Thank you.

This is likely a lag in the analytics pipeline. It can take some time for the dashboard to accurately report the session.

For Issue 1, if you’re using RoomComposite egress, the recording is tied to participant presence, not the dashboard “room duration.” It stops when all participants (including agents or egress-related participants) leave the room, so lingering participants can extend the recording beyond the visible room session time. See RoomComposite & web egress.

For Issue 2, onDisconnected in <LiveKitRoom /> only fires when the client actually disconnects. If the server-side room ends but the client connection remains active or isn’t explicitly disconnected, the callback may not trigger. See React best practices.

Are you using RoomComposite or Track egress, and do you see any agent or SIP participants still connected after 3:03 PM IST?

I am using Room Composite and I need a reliable way to know when a session ends — regardless of the reason — so that I can call my backend API.

What I have tried:

First I used:

python

@server.rtc_session(agent_name="interview-agent", on_session_end=on_session_end)

But on_session_end was not being called for some rooms.

Then I switched to:

python

@session.on("close")
def on_closed(session):

But for the past 2 days I have noticed that for some rooms, the agent disconnects — either because the interview time completed or because I called session.shutdown(drain=True) — and neither onDisconnected nor @session.on("close") is triggered.

Could you please help me understand the following:

1. What is the correct way to end an interview session? Which of the following should I use and what is the difference?

  • session.shutdown()

  • session.shutdown(drain=True)

  • ctx.room.disconnect()

2. How should the React UI know when the agent has disconnected? Currently I am relying on the onDisconnected callback of the <LiveKitRoom/> component. Is this the correct approach?

3. Is delete_room_on_close=True the correct config for my use case? Please confirm if this is the right setting for an interview session.

4. How can I differentiate between agent disconnect and a network reconnection on the frontend? I do not want to show the interview ended screen if the agent is simply reconnecting due to a network issue. I only want to show the interview ended screen when the user initiates the end or when session.shutdown() is called. How can my React app know the difference?

5. How can I properly inform the user why the session ended? Sometimes I see participants rejoining and the LiveKit dashboard shows CONNECTION_TIMEOUT. I want to show the user a meaningful message based on the actual disconnect reason.

Thank you.

I’m getting very confused by the slew of similar issues and questions.

This feels like the same question as Urgent: on_session_end callback not triggering in Agents SDK - #5 by Vishal_Maurya and you already asked about delete_room_on_close in this thread: Agent Disconnects After session.shutdown(drain=True) but User Remains Stuck in Room — Production Issue - #3 by Vishal_Maurya .

It becomes very difficult to help when you cross post questions between different topics.

First, I want to sincerely apologise for the confusion and cross-posting. I completely understand how that makes tracking difficult for you and the team.

The reason for the multiple threads is that the session lifecycle is heavily interconnected. Every time I applied a recommended fix for one issue (like changing delete_room_on_close=False or switching from room.disconnect() to session.shutdown()), it created a new edge case in my production environment (like zombie rooms or my backend API failing to trigger).

Moving forward, I will keep all questions regarding the Session Lifecycle, Room Cleanup, and Disconnects strictly in this thread.

To get straight to the core of what I am trying to solve right now:

I am facing a new bug in room RM_5Ubt4d5ovXri. The logs show: Participant left (CONNECTION_TIMEOUT). I don’t know exactly what caused this, but it highlights the exact problem I am trying to solve with my React UI.

Also, can you give me a solution for each point of the above raised issue

My Goal / Requirement:

  1. Unintentional Disconnect (Network drop, CONNECTION_TIMEOUT, etc.): The UI should show a “Reconnecting…” state and attempt to restore the connection for both the user and the agent. The interview should not end.

  2. Intentional Disconnect (Agent intentionally calls session.shutdown(drain=True) or user clicks “End Call”): The UI should gracefully transition to the “Interview Ended” screen.

My Core Questions to achieve this:

  1. How can my React frontend distinguish between a CONNECTION_TIMEOUT (where it should reconnect) and an intentional session.shutdown() (where it should end the interview)? Right now, my just sees a disconnect and blindly ends the interview for the user.

  2. When a CONNECTION_TIMEOUT does happen, what is the recommended way to handle the reconnection for both the React client and the Python Agent so the interview can continue?

I appreciate your patience and help in getting this architecture bulletproof for production. Let’s resolve this workflow here.

The React frontend connection state is here: ConnectionState | React Components | LiveKit Documentation. Please also see here:Connecting to LiveKit | LiveKit Documentation, so you will only see a ‘reconnecting’ if it’s a full restart, otherwise the collection loss should be seamless and short to the user

In the event of an intentional disconnect from the agent, I would expect the connection state to be disconnected