Summary
Opening a channel that contains a message with U+FFFC (OBJECT REPLACEMENT CHARACTER) alone on its own line crashes the React root on Android (IllegalArgumentException: Layout: -2 < 0), leaving the app permanently stuck on the splash screen. iOS and web render the same channel fine.
Environment Information
- Device Name: Pixel 6 emulator (arm64, Android 16 / API 36, Google APIs image); also reproduced by multiple end users on physical Android devices
- OS Version: Android 16
- Mattermost App Version: 2.42.2 (Build 787, GitHub release APK)
- Mattermost Server Version: 11.9.0 (self-hosted, Team edition)
Steps to reproduce
-
Post a message whose last line consists only of U+FFFC, e.g. (note the invisible U+FFFC after the blank line):
Easiest programmatic repro: POST /api/v4/posts with "message": "some text\n\n".
Real-world origin: iOS users copy-pasting text together with an inline image puts U+FFFC into the message text.
-
Open the channel in the Android app.
Notes from bisecting the trigger:
- U+FFFC inline within a line of text is harmless (renders as the OBJ glyph).
- U+FFFC alone on its own line crashes 100% of the time.
- Because the post sits in the channel's recent page, the crash re-triggers on every channel open. Reinstalling the app does not help.
Expected behavior
The message renders (or the character is ignored), like on iOS and web.
Observed behavior (that appears unintentional)
The channel screen never appears; the app falls back to the splash screen and stays there ("frozen image"). End users reported it as the app being stuck/crashed for one specific channel, surviving reinstall and restart.
Logcat shows a native exception during text measurement, which React Native treats as a component error and destroys the React host:
BridgelessReact: ReactHost{0}.handleHostException(message = "Error: Exception in HostFunction: java.lang.IllegalArgumentException: Layout: -2 < 0
at android.text.Layout.<init>(Layout.java:375)
at android.text.BoringLayout.<init>(BoringLayout.java:274)
at android.text.BoringLayout.make(BoringLayout.java:68)
at com.facebook.react.views.text.TextLayoutManager.createLayout(TextLayoutManager.kt:611)
at com.facebook.react.views.text.TextLayoutManager.createLayout(TextLayoutManager.kt:821)
at com.facebook.react.views.text.TextLayoutManager.createLayoutForMeasurement(TextLayoutManager.kt:742)
at com.facebook.react.views.text.TextLayoutManager.measureText(TextLayoutManager.kt:993)
at com.facebook.react.fabric.FabricUIManager.measureText(FabricUIManager.java:637)
...
This error is located at:, stack:
commitMutationEffectsOnFiber@1:379746
...
followed by ReactHost{0}.getOrCreateDestroyTask(): Starting React Native destruction, after which only the splash screen remains.
TurboLogger right before the crash: channel switch to <channel> <id> 1083.0 ms, and the error report has "isComponentError": true.
Possible fixes
The negative width (-2, suspiciously equal to WRAP_CONTENT) reaches android.text.BoringLayout via RN's TextLayoutManager.measureText, so the underlying overflow is arguably a react-native bug. On the Mattermost side, sanitizing U+FFFC in the markdown/text rendering path (e.g. stripping it or replacing standalone occurrences before it reaches a <Text> measure) would avoid the crash entirely and match what users expect, since the character is an artifact of iOS copy-paste rather than intentional content.
Possibly related older reports with matching symptoms but no root cause identified: #7738 (app freezes when opening certain channels), #8234 (error when opening a specific channel).
Server-side workaround that fixed it for our deployment: strip U+FFFC from the affected posts (via PUT /api/v4/posts/{id}/patch so clients resync).
Summary
Opening a channel that contains a message with U+FFFC (OBJECT REPLACEMENT CHARACTER) alone on its own line crashes the React root on Android (
IllegalArgumentException: Layout: -2 < 0), leaving the app permanently stuck on the splash screen. iOS and web render the same channel fine.Environment Information
Steps to reproduce
Post a message whose last line consists only of U+FFFC, e.g. (note the invisible U+FFFC after the blank line):
Easiest programmatic repro:
POST /api/v4/postswith"message": "some text\n\n".Real-world origin: iOS users copy-pasting text together with an inline image puts U+FFFC into the message text.
Open the channel in the Android app.
Notes from bisecting the trigger:
Expected behavior
The message renders (or the character is ignored), like on iOS and web.
Observed behavior (that appears unintentional)
The channel screen never appears; the app falls back to the splash screen and stays there ("frozen image"). End users reported it as the app being stuck/crashed for one specific channel, surviving reinstall and restart.
Logcat shows a native exception during text measurement, which React Native treats as a component error and destroys the React host:
followed by
ReactHost{0}.getOrCreateDestroyTask(): Starting React Native destruction, after which only the splash screen remains.TurboLoggerright before the crash:channel switch to <channel> <id> 1083.0 ms, and the error report has"isComponentError": true.Possible fixes
The negative width (-2, suspiciously equal to
WRAP_CONTENT) reachesandroid.text.BoringLayoutvia RN'sTextLayoutManager.measureText, so the underlying overflow is arguably a react-native bug. On the Mattermost side, sanitizing U+FFFC in the markdown/text rendering path (e.g. stripping it or replacing standalone occurrences before it reaches a<Text>measure) would avoid the crash entirely and match what users expect, since the character is an artifact of iOS copy-paste rather than intentional content.Possibly related older reports with matching symptoms but no root cause identified: #7738 (app freezes when opening certain channels), #8234 (error when opening a specific channel).
Server-side workaround that fixed it for our deployment: strip U+FFFC from the affected posts (via
PUT /api/v4/posts/{id}/patchso clients resync).