Repository navigation
Release packages - #1327
Merged
Merged
Release packages#1327
Conversation
knope-bot
Bot
force-pushed
the
knope/release
branch
from
August 14, 2026 10:14
198fd73 to
743b027
Compare
knope-bot
Bot
force-pushed
the
knope/release
branch
4 times, most recently
from
August 20, 2026 00:57
201dd8a to
0c4b07b
Compare
cloudwebrtc
approved these changes
Aug 20, 2026
knope-bot
Bot
force-pushed
the
knope/release
branch
2 times, most recently
from
August 24, 2026 08:08
d211d38 to
4db849c
Compare
knope-bot
Bot
force-pushed
the
knope/release
branch
3 times, most recently
from
August 25, 2026 15:36
d734f95 to
21b8d01
Compare
knope-bot
Bot
force-pushed
the
knope/release
branch
from
August 25, 2026 16:12
21b8d01 to
6327ada
Compare
xianshijing-lk
added a commit
that referenced
this pull request
Oct 19, 2026
## Summary Fixes a regression introduced by #1376: an RPC call whose reply arrives just after its recipient leaves the room is failed, even though the call succeeded. #1376 added `RpcClientManager::handle_participant_disconnected`, which removes a call's pending ack and response the moment its recipient disconnects. That was a real fix — before it, a recipient leaving mid-call stranded the caller for the full 15s response timeout and reported `ResponseTimeout` instead of the disconnect that actually ended the call. But it assumed "participant left" implies "no reply is coming", and that is not true: the departure is announced on the **signalling connection** (`signal_response::Message::Update` → `SessionEvent::ParticipantUpdate`), while the ack and response travel on the **data channel**. Nothing orders the two against each other. `lk.sip.EndCall` produces the losing order routinely, because the SIP participant leaves the room as soon as it has ended the call it was just asked to end. The reply then arrives to find its entry already gone, is discarded with `Response received for unexpected RPC request`, and the caller gets `RECIPIENT_DISCONNECTED` (1503) for a call that in fact completed. A caller that retries goes on to address a participant no longer in the room, nothing acks, and it spends the full `max_round_trip_latency` — 7s by default — before failing with `CONNECTION_TIMEOUT`. ## Reported impact Surfaced by a customer upgrading `livekit-agents` 1.7.1 → 1.8.5, whose E2E suite went from a historical <1% failure rate on `lk.sip.EndCall` to **13 of ~44 calls**, each costing ~11s of extra session time (2s before the retry + the 7s ack timeout). The version boundary matches this change exactly: | agents | pins | `rust-sdks` submodule | has #1376? | |---|---|---|---| | 1.8.3 | `livekit==1.1.18` | `2d9f01ab` (Release #1327) | no | | 1.8.4 | `livekit==1.1.20` | `5a656c4b` (Release #1423) | **yes** | | 1.8.5 | `livekit==1.1.20` | `5a656c4b` | **yes** | which is consistent with their report of 260 clean scenarios after downgrading to 1.8.3. (Note for anyone triaging the same report: the break is 1.8.4, not 1.8.5 — both pin the same `livekit-rtc`.) The `EndCall` itself always landed; nothing left calls up. The damage was a false error plus the wasted retry. ## Change A disconnect now **shortens** the wait instead of ending it. `handle_participant_disconnected` no longer removes the pending entries — dropping them is what turns an in-flight reply into an "unexpected RPC request". It signals each affected caller over a per-leg `oneshot`, and the caller then waits up to `DISCONNECT_GRACE_PERIOD` (2s), never past its own timeout, for a reply already on the wire. Per-leg signals mean a disconnect seen while waiting on the ack is still remembered once the call moves on to the response. A recipient that really did leave without replying still fails fast with `RECIPIENT_DISCONNECTED` rather than running out the 15s response timeout, so #1376's improvement is preserved. `fail_all_pending` (room close) still fails immediately — the data channel is gone, nothing more can arrive. ## Tests `livekit-rpc/src/tests.rs` — three new tests on virtual time, driving the exact event ordering that caused the bug: - `test_response_after_disconnect_still_resolves_caller` — the repro: ack, disconnect, then the response 50ms later (matching the ~45ms gap seen in the field). **Fails on `main`** with `RpcError { code: 1503, message: "Recipient disconnected" }` — the reported symptom — and passes here. - `test_ack_after_disconnect_still_resolves_caller` — same race on the ack leg. Also fails on `main`. - `test_disconnect_grace_period_does_not_wait_out_response_timeout` — the grace period is a reprieve, not a second response timeout. Reverting only `client.rs` to `main` and keeping the tests gives 25 passed / 2 failed; with the fix, 27 passed. The existing `test_participant_disconnect_fails_pending_call` still passes and now also asserts the call ends well inside its 30s response timeout. `livekit/tests/rpc_test.rs` — `test_rpc_recipient_leaving_without_replying_fails_promptly` covers the same contract end-to-end against a live server: a handler that never replies, the recipient closes its room, and the caller must fail with `RECIPIENT_DISCONNECTED` inside 15s despite a 60s response timeout. This guards the fast-fail behaviour from being reverted along with the race fix. Worth being explicit about the split: the race itself cannot be forced end-to-end — it is a sub-50ms window owned by two independent transports, and a client-side room close tears down the data channel, so the reply would be genuinely lost rather than merely late. The deterministic coverage therefore lives in the unit tests, at the seam where the event ordering is actually decided. The e2e test is compiled but not run locally (it needs a server); CI runs it under `__lk-e2e-test`. ## Follow-up, not in this PR `perform_rpc` to an identity that is not in the room does not fail fast: it sends into the void and waits the full 7s ack timeout before returning `CONNECTION_TIMEOUT`. `RpcTransport` already exposes `remote_identities()`, so this could return `RECIPIENT_NOT_FOUND` (1401) immediately. Left out because it changes an API-visible error code on an existing path. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Ryan Gaus <ryan.gaus@livekit.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
Merging this pull request will create these releases
webrtc-sys-build 0.3.19 (2026-08-25)
Fixes
fix: bump libwebrtc to webrtc-b9233c3-2 so TURN/TLS can use the OS trust store
WebRTC validates TURN/TLS against a small set of anchors compiled into
rtc_base/ssl_roots.h, generated in 2023 from Google's own PKI list. It has noAmazon, Starfield Services or ISRG roots, so a relay-only connection to a TURN
server fronted by AWS ACM or Let's Encrypt times out with
unknown_caeventhough the host OS trusts the chain.
This build picks up webrtc-sdk/webrtc#277, which falls back to the operating
system's trust store when the built-in anchors yield no path. It sits in
rtc_basebelow every SDK, so the C++ API that webrtc-sys binds is coveredwithout any Rust-side change.
livekit-api 0.6.4 (2026-08-25)
Fixes
Moves access-token generation and verification into a new
livekit-tokencrate.livekit_api::access_token::*continues to resolve to the same types via are-export, so no consumer changes are needed.
Also fixes the
services-tokioandservices-asyncfeatures, which used theaccess-token types without declaring the
access-tokenfeature. Building with--no-default-features --features services-tokiopreviously failed to compile.yuv-sys 0.3.15 (2026-08-25)
Fixes
libwebrtc 0.3.46 (2026-08-25)
Features
feat: enable WARP (SPED + SNAP) by default, gated by the server
WARP is now always enabled on the client and negotiated with the SFU: SPED
(DTLS-in-STUN) via the
WebRTC-IceHandshakeDtlsfield trial, and SNAP(SCTP-INIT-in-SDP) via the
RtcConfiguration.enable_sctp_snapfield. When theserver does not enable WARP it is not advertised and the connection falls back to
plain DTLS/SCTP, so there is no client-side toggle.
BREAKING CHANGE:
libwebrtc::RtcConfigurationis now#[non_exhaustive]and has anew
enable_sctp_snapfield. Construct it fromRtcConfiguration::default()and setthe fields you need instead of a struct literal.
Fixes
fix: bump libwebrtc to webrtc-b9233c3-2 so TURN/TLS can use the OS trust store
WebRTC validates TURN/TLS against a small set of anchors compiled into
rtc_base/ssl_roots.h, generated in 2023 from Google's own PKI list. It has noAmazon, Starfield Services or ISRG roots, so a relay-only connection to a TURN
server fronted by AWS ACM or Let's Encrypt times out with
unknown_caeventhough the host OS trusts the chain.
This build picks up webrtc-sdk/webrtc#277, which falls back to the operating
system's trust store when the built-in anchors yield no path. It sits in
rtc_basebelow every SDK, so the C++ API that webrtc-sys binds is coveredwithout any Rust-side change.
webrtc-sys 0.3.43 (2026-08-25)
Fixes
fix: bump libwebrtc to webrtc-b9233c3-2 so TURN/TLS can use the OS trust store
WebRTC validates TURN/TLS against a small set of anchors compiled into
rtc_base/ssl_roots.h, generated in 2023 from Google's own PKI list. It has noAmazon, Starfield Services or ISRG roots, so a relay-only connection to a TURN
server fronted by AWS ACM or Let's Encrypt times out with
unknown_caeventhough the host OS trusts the chain.
This build picks up webrtc-sdk/webrtc#277, which falls back to the operating
system's trust store when the built-in anchors yield no path. It sits in
rtc_basebelow every SDK, so the C++ API that webrtc-sys binds is coveredwithout any Rust-side change.
feat: enable WARP (SPED + SNAP) by default, gated by the server
WARP is now always enabled on the client and negotiated with the SFU: SPED
(DTLS-in-STUN) via the
WebRTC-IceHandshakeDtlsfield trial, and SNAP(SCTP-INIT-in-SDP) via the
RtcConfiguration.enable_sctp_snapfield. When theserver does not enable WARP it is not advertised and the connection falls back to
plain DTLS/SCTP, so there is no client-side toggle.
BREAKING CHANGE:
libwebrtc::RtcConfigurationis now#[non_exhaustive]and has anew
enable_sctp_snapfield. Construct it fromRtcConfiguration::default()and setthe fields you need instead of a struct literal.
imgproc 0.3.20 (2026-08-25)
Fixes
livekit 0.8.4 (2026-08-25)
Features
feat: enable WARP (SPED + SNAP) by default, gated by the server
WARP is now always enabled on the client and negotiated with the SFU: SPED
(DTLS-in-STUN) via the
WebRTC-IceHandshakeDtlsfield trial, and SNAP(SCTP-INIT-in-SDP) via the
RtcConfiguration.enable_sctp_snapfield. When theserver does not enable WARP it is not advertised and the connection falls back to
plain DTLS/SCTP, so there is no client-side toggle.
BREAKING CHANGE:
libwebrtc::RtcConfigurationis now#[non_exhaustive]and has anew
enable_sctp_snapfield. Construct it fromRtcConfiguration::default()and setthe fields you need instead of a struct literal.
Fixes
fix: bump libwebrtc to webrtc-b9233c3-2 so TURN/TLS can use the OS trust store
WebRTC validates TURN/TLS against a small set of anchors compiled into
rtc_base/ssl_roots.h, generated in 2023 from Google's own PKI list. It has noAmazon, Starfield Services or ISRG roots, so a relay-only connection to a TURN
server fronted by AWS ACM or Let's Encrypt times out with
unknown_caeventhough the host OS trusts the chain.
This build picks up webrtc-sdk/webrtc#277, which falls back to the operating
system's trust store when the built-in anchors yield no path. It sits in
rtc_basebelow every SDK, so the C++ API that webrtc-sys binds is coveredwithout any Rust-side change.
Moves access-token generation and verification into a new
livekit-tokencrate.livekit_api::access_token::*continues to resolve to the same types via are-export, so no consumer changes are needed.
Also fixes the
services-tokioandservices-asyncfeatures, which used theaccess-token types without declaring the
access-tokenfeature. Building with--no-default-features --features services-tokiopreviously failed to compile.livekit-common 0.1.2 (2026-08-25)
Fixes
BytesUniFFI custom type once inlivekit-commonand borrow it from each component withuniffi::use_remote_type!, so the converter is emitted once and the post-generation Swift workaround is no longer neededlivekit-token-source 0.1.2 (2026-08-25)
Features
livekit-token 0.1.1 (2026-08-25)
Fixes
Moves access-token generation and verification into a new
livekit-tokencrate.livekit_api::access_token::*continues to resolve to the same types via are-export, so no consumer changes are needed.
Also fixes the
services-tokioandservices-asyncfeatures, which used theaccess-token types without declaring the
access-tokenfeature. Building with--no-default-features --features services-tokiopreviously failed to compile.livekit-data-stream 0.1.3 (2026-08-25)
Fixes
livekit-datatrack 0.1.14 (2026-08-25)
Fixes
BytesUniFFI custom type once inlivekit-commonand borrow it from each component withuniffi::use_remote_type!, so the converter is emitted once and the post-generation Swift workaround is no longer neededlivekit-uniffi 0.1.9 (2026-08-25)
Fixes
RemoteDataTrack.set_pipeline_optionsandRemoteDataTrackPipelineOptions(max_partial_frames) over UniFFI, matching the JS and Rust SDKsBytesUniFFI custom type once inlivekit-commonand borrow it from each component withuniffi::use_remote_type!, so the converter is emitted once and the post-generation Swift workaround is no longer neededMoves access-token generation and verification into a new
livekit-tokencrate.livekit_api::access_token::*continues to resolve to the same types via are-export, so no consumer changes are needed.
Also fixes the
services-tokioandservices-asyncfeatures, which used theaccess-token types without declaring the
access-tokenfeature. Building with--no-default-features --features services-tokiopreviously failed to compile.livekit-ffi 0.12.76 (2026-08-25)
Fixes
fix: bump libwebrtc to webrtc-b9233c3-2 so TURN/TLS can use the OS trust store
WebRTC validates TURN/TLS against a small set of anchors compiled into
rtc_base/ssl_roots.h, generated in 2023 from Google's own PKI list. It has noAmazon, Starfield Services or ISRG roots, so a relay-only connection to a TURN
server fronted by AWS ACM or Let's Encrypt times out with
unknown_caeventhough the host OS trusts the chain.
This build picks up webrtc-sdk/webrtc#277, which falls back to the operating
system's trust store when the built-in anchors yield no path. It sits in
rtc_basebelow every SDK, so the C++ API that webrtc-sys binds is coveredwithout any Rust-side change.
feat: enable WARP (SPED + SNAP) by default, gated by the server
WARP is now always enabled on the client and negotiated with the SFU: SPED
(DTLS-in-STUN) via the
WebRTC-IceHandshakeDtlsfield trial, and SNAP(SCTP-INIT-in-SDP) via the
RtcConfiguration.enable_sctp_snapfield. When theserver does not enable WARP it is not advertised and the connection falls back to
plain DTLS/SCTP, so there is no client-side toggle.
BREAKING CHANGE:
libwebrtc::RtcConfigurationis now#[non_exhaustive]and has anew
enable_sctp_snapfield. Construct it fromRtcConfiguration::default()and setthe fields you need instead of a struct literal.
Moves access-token generation and verification into a new
livekit-tokencrate.livekit_api::access_token::*continues to resolve to the same types via are-export, so no consumer changes are needed.
Also fixes the
services-tokioandservices-asyncfeatures, which used theaccess-token types without declaring the
access-tokenfeature. Building with--no-default-features --features services-tokiopreviously failed to compile.