Skip to content

performRpc can stall under degraded network on React Native/iOS in livekit-client 2.18.x #1937

@zkewal

Description

@zkewal

Describe the bug

What I'm expecting

Reliable performRpc() calls should either:

  • succeed under temporary network degradation, or
  • fail explicitly with a timeout / reconnect-related error.

After the network recovers, the room should recover without requiring a reconnect or joining a new room.

What happens instead

In our React Native iOS app, after upgrading livekit-client from 2.15.8 to 2.18.3 / 2.18.4, reliable RPC calls can stop reaching the backend after mild or moderate mid-session network degradation.

The room starts healthy and RPCs work normally at first. After enabling network degradation and sending a few RPCs, one RPC can get stuck before the request is actually sent:

  • the backend never receives the RPC request
  • the request does not appear to enter normal local ACK / response tracking
  • reconnecting or joining a new room restores behavior immediately

This is blocking our upgrade from the older LiveKit client stack.

Reproduction

I do not yet have a minimal standalone repro repository, but the shortest app-level repro I have is:

  1. Use a React Native iOS app with one of these dependency sets:

    • @livekit/react-native 2.9.2
    • @livekit/react-native-webrtc 137.0.2
    • livekit-client 2.18.4

    or

    • @livekit/react-native 2.9.6
    • @livekit/react-native-webrtc 137.0.2
    • livekit-client 2.18.3
  2. Connect to a room with a remote participant or backend participant that registers a simple RPC handler.

  3. From the local participant, repeatedly call performRpc().

await room.localParticipant.performRpc({
  destinationIdentity,
  method: 'ping',
  payload: '',
});
  1. Start on a healthy network and confirm RPC works normally.
  2. After the room is connected and stable, enable Network Link Conditioner with mild or moderate degradation (added latency / loss).
  3. Continue sending RPCs for a few turns while the degraded network is active.
  4. In the bad state, one RPC eventually hangs before send:
    • the remote side never receives the request
    • the local app does not see the request enter its normal pending ACK / pending response bookkeeping
  5. Disable the network conditioner.
  6. The stuck state can persist until reconnecting or joining a new room.

Known non-repro / good stack:

  • @livekit/react-native 2.9.2
  • @livekit/react-native-webrtc 137.0.2
  • livekit-client 2.15.8

Logs

I do not yet have a minimal standalone repro log with `setLogLevel('debug')` enabled from app startup.

What our app-level instrumentation consistently shows for the stuck request:
- `performRpc()` is entered
- the backend never logs or receives the RPC request
- the local request never appears to enter normal pending ACK / pending response tracking
- reconnecting or joining a new room restores RPC delivery immediately

If useful, I can follow up with a cleaner repro run that adds temporary logging around:
- `sendDataPacket(..., RELIABLE)`
- `waitForBufferStatusLow()`
- reliable data channel `bufferedAmount`
- reliable data channel `readyState`

System Info

Client runtime: React Native iOS app (not browser)
Browser: N/A

Dev machine:
ProductName: macOS
ProductVersion: 26.4.1
BuildVersion: 25E253

Node: v22.22.1
Yarn: 4.12.0

Known good stack:
@livekit/react-native: 2.9.2
@livekit/react-native-webrtc: 137.0.2
livekit-client: 2.15.8

Known bad stack:
@livekit/react-native: 2.9.2
@livekit/react-native-webrtc: 137.0.2
livekit-client: 2.18.4

Known bad stack:
@livekit/react-native: 2.9.6
@livekit/react-native-webrtc: 137.0.2
livekit-client: 2.18.3

Severity

blocking an upgrade

Additional Information

A few points that may help with triage:

  • The same React Native wrapper version can be either good or bad depending on the resolved livekit-client version.

    • good: @livekit/react-native 2.9.2 + livekit-client 2.15.8
    • bad: @livekit/react-native 2.9.2 + livekit-client 2.18.4
      This is the main reason I believe this issue belongs in client-sdk-js rather than client-sdk-react-native.
  • From source review, the most suspicious regression window is between 2.15.8 and 2.18.x, especially around:

    • 8777025c - Wait for dc buffer status low for all published packets (#1691)
    • d6306572 - Add new rtc path with implicit single peer connection mode (#1785)
  • The behavior matches a failure mode where performRpc() stalls before the reliable data channel send completes:

    • performRpc() registers pending ACK / response handlers only after publishRpcRequest() returns
    • in newer versions, reliable sendDataPacket() waits on waitForBufferStatusLow() before dc.send(...)
    • if that wait stalls under degraded transport, the RPC never reaches the backend and no normal RPC timeout bookkeeping is installed
  • I have not yet re-tested on the absolute latest livekit-client release. If needed, I can do that and also provide a smaller repro with debug logging enabled from process startup.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions