Skip to content

fix(MatrixRTCSession): replace no-arg .finally() with .then(fn, fn) to fix crash on React Native / Hermes#5307

Open
JeanLuX wants to merge 2 commits intomatrix-org:developfrom
JeanLuX:fix/matrixrtc-no-arg-promise-finally
Open

fix(MatrixRTCSession): replace no-arg .finally() with .then(fn, fn) to fix crash on React Native / Hermes#5307
JeanLuX wants to merge 2 commits intomatrix-org:developfrom
JeanLuX:fix/matrixrtc-no-arg-promise-finally

Conversation

@JeanLuX
Copy link
Copy Markdown

@JeanLuX JeanLuX commented Apr 30, 2026

Fixes #5308

What

ensureRecalculateSessionMembers() called .finally() with no argument to swallow a previous rejection before chaining the next recalculation.

On React Native / Hermes, the RN Promise polyfill (promise/setimmediate/finally.js) requires onFinally to be a callable — passing undefined throws immediately:

TypeError: undefined is not a function

This rejects initialMembershipCalculated for every room at startup, silently breaking the entire RTC session membership layer on all React Native clients.

Fix

Replace .finally().then(fn) with .then(fn, fn) — semantically equivalent on all runtimes:

-    this.recalculateSessionMembersPromise = this.recalculateSessionMembersPromise.finally().then(() => this.recalculateSessionMembers());
+    this.recalculateSessionMembersPromise = this.recalculateSessionMembersPromise.then(
+      () => this.recalculateSessionMembers(),
+      () => this.recalculateSessionMembers(),
+    );

File: src/matrixrtc/MatrixRTCSession.tsensureRecalculateSessionMembers()

Verified on

Component Version
matrix-js-sdk 41.4.0
React Native 0.83.6
Hermes bundled with RN 0.83.6
Expo SDK 55

Checklist

  • Semantics preserved — recalculation runs on both resolve and reject
  • No behaviour change on browser / Node.js runtimes
  • Unit tests pass locally (yarn test)
  • Signed-off-by / CLA (if required)

JeanLuX added 2 commits April 30, 2026 14:55
…ejected) to fix crash on React Native / Hermes

Calling .finally() without an argument works in browsers and Node.js but
throws a TypeError on Hermes (the JS engine used by React Native):

  TypeError: undefined is not a function

This happens because the React Native Promise polyfill requires the
onFinally argument to be a function. When it receives undefined it throws
immediately, before recalculateSessionMembers() even runs.

The crash fires once per room at startup (via MatrixRTCSessionManager.start())
and leaves every MatrixRTCSession's initialMembershipCalculated promise
permanently rejected, silently breaking RTC session management on all React
Native clients.

Fix: replace the no-arg .finally().then(fn) pattern with an explicit
two-handler .then(onFulfilled, onRejected) that achieves identical semantics —
run recalculateSessionMembers() whether the previous promise resolved or
rejected — while being safe on all runtimes.

Signed-off-by: Jean-Luc Cenatus <contact@jcenatus.net>
…ionMembers after rejection

Verify that ensureRecalculateSessionMembers() still runs correctly even
when recalculateSessionMembersPromise is in a rejected state.

This guards against the React Native / Hermes regression where the previous
.finally() call (no argument) threw a TypeError and left the promise chain
permanently broken.

Signed-off-by: Jean-Luc Cenatus <contact@jcenatus.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Z-Community-PR Issue is solved by a community member's PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MatrixRTCSession: .finally() without argument crashes on React Native / Hermes — TypeError: undefined is not a function

1 participant