We started one room-composite egress for room RM_LSjTA3upCArD (single start_room_composite_egress call, no client retries). The session events show the egress was triggered twice for the room.
As a result we received multiple egress_ended / EGRESS_COMPLETE webhooks for the same egressId (EG_5Ef7qsW65bH9) with different startedAt/endedAt — and the first ones arrived while the room was still active (the call hadn’t ended yet), kicking off our post-call processing prematurely.
The core problem: all webhooks carry the same egressId, so there is no way to identify whether an egress_ended webhook came from the duplicated egress or the original one — or which one is final. Both also wrote to the same S3 filepath (the later one overwrote the earlier file).
Questions:
Why was the egress triggered twice for one StartEgress request?
How can a webhook consumer distinguish the original vs duplicated egress run (or identify the final egress_ended), given they share one egressId?
Why was the egress triggered twice for one StartEgress request?
It looks like two simultaneous Egress processes were spun up, but I’m not sure why. I have flagged this internally.
How can a webhook consumer distinguish the original vs duplicated egress run (or identify the final egress_ended), given they share one egressId?
That’s not possible, because this is not intended behaviour (you should not be receiving duplicate webhooks like this, with the same ID, so it should not be up to you to distinguish them)
StartRoomCompositeEgress returns deadline_exceeded (408) — does the egress still get created server-side? (we then see duplicate egress-completion handling)
Setup: voice agents on livekit-agents 1.4.6 / livekit 1.1.2 / livekit-api 1.0.7 (Python 3.11), outbound SIP telephony, LiveKit Cloud (project p_3tqm7ro6kbs). We start a room-composite, audio-only, dual-channel egress (OGG → S3) right after the callee answers and the agent joins.
What happened (room RM_HVDLJNxUhj8R, 2026-06-08):
14:07:35.728 UTC — our first StartRoomCompositeEgress call returned:
We retried, and at ~14:07:37.6 UTC the retry succeeded and returned egress EG_44t6CLtHEgMC. The call recorded normally and the audio uploaded to S3.
After the call ended (14:08:34 UTC), our webhook receiver ran post-egress completion processing ~5 times for this single call within ~8 seconds (14:08:39–14:08:47) — repeated downloads + transcript generations, and multiple concurrent redaction passes that collided: one wrote the redacted file successfully, another failed with "output file already exists".
We only ever observed one egress ID in our own logs (EG_44t6CLtHEgMC, from the successful retry). But the repeated completion processing makes us suspect the timed-out first StartEgress (the 408) actually created an egress server-side — one whose ID we never received (the response timed out) — which then also emitted a completion webhook. Net: one logical recording, but potentially two egress instances and two egress_ended webhooks, driving duplicated post-call processing on our side.
Hi Zaheer, your hypothesis sounds very plausible since I see that EG_MNpsCYyGTYiy was also spawned for this session. I would have expected your webhook to distinguish between the two egresses in this instance however since they had different IDs. This sounds like a different issue from the original issue in this thread, it looks more like the issue described here: Error during egress request - #9 by Zaheer_Abbas
I’m honestly a bit lost at this point, I want to make sure you have the support you need but it feels like there are a lot of different but related threads. Are you getting the support you need?
Thanks for responding, yes this is a separate issue where in we are able to distinguish the two different egress requests.
I added in this same thread as it belongs to the same duplicate egress. We triggered a duplicate egress because the Room Compose Egress API timed out on LiveKit Cloud. Should we NOT trigger retries in this case?
Apologies for causing confusion - this is a different issue but raised in same thread because of duplicate egress being triggered. Happy to move this to a separate post.
Still seeing duplicate egress requests even for the ones that have timed out. Should we NOT retry if we receive a timeout request? We retry so that we don’t fail on egress requests as it is a critical piece for us
Was merged. After looking at cloud deployments, and speaking with Milos, I can confirm that this PR has not yet landed on our production deployments and is still under test. Milos tells me the plan is to deploy to production today or tomorrow, after which time I would expect instances of this issue to reduce.
Should we NOT retry if we receive a timeout request?
My understanding is that this issue, i.e. duplicate egress trigged for a room [with the same Egress ID], is not caused by the retry, but is an internal cross-region issue with LiveKit cloud separate from your retry. If you retried, I thought that ended up with multiple Egress IDs, which you would be able to differentiate.
This issue is a separate from the PR that milos has raised but triggers the same outcome - duplicate egress.
I’m not so sure, I see duplicate Egress participants being created on two different nodes for EG_A6mYepNmawtr which is the same symptom as the earlier EG_5Ef7qsW65bH9. The PR was designed to mitigate against this kind of duplication.
But, the actual question is “what should you do if the client API returns status 408? Retry?”. My personal instinct would be to try listEgress() after some short delay, and then if there is an active egress, call stopEgress(id) and then try to start again. If listEgress returns empty, then you could still restart anyway. What are you currently doing when you get a 408? Or any error?
My personal instinct would be to try listEgress() after some short delay, and then if there is an active egress, call stopEgress(id) and then try to start again.
We would lose some parts of speech just doing this activity
What are you currently doing when you get a 408? Or any error?
If we receive a TwripError on Start Egress API - we retry for 5xx and 408, 429 codes