Skip to content

[Bug]: Android native crash in rive-react-native on wallet home onboarding checklist (WalletHomeOnboardingSteps) #31103

@vinnyhoward

Description

@vinnyhoward

Describe the bug

##Summary

Fatal native crash on Android originating inside rive-react-native's checklist Rive animation rendered by WalletHomeOnboardingSteps. ~2.3K production users / ~2.6K events affected on production 7.79.0. Crash signature is rive_android::JNIExceptionHandler::check_and_rethrow — Sentry classifies as SIGSEGV; local repros captured the same code path as SIGABRT (the death mode differs by device based on whether ART's CheckJNI is active, but the failing code path is the same).

Reproducible deterministically on both arm64 emulator and arm64 physical device.

Sentry

  • Issue: METAMASK-MOBILE-5VF9

  • First seen: 2026-05-21, in release 7.79.0 (4532) — the earliest 7.79 build

  • Latest event: Pixel 9 Pro on Android 16, release 7.79.0 (5225), production

  • ~2.3K users / ~2.6K events (ongoing)

M- echanism: signalhandler, unhandled, fatal, on the Rive native worker thread

Component identification

The crash originates inside the instance mounted by app/components/UI/WalletHomeOnboardingSteps/WalletHomeOnboardingSteps.tsx. This is the only consumer shipped to 7.79 production users:

MoneyOnboardingView / RiveOnboardingStepper (introduced in PR #30137, the original suspect) is feature-flagged off in production at the time of this writing per @pedro.aste's feature-flag tracker — so it cannot be the source of the production events even though it produces a similar crash signature in local testing.

OnboardingAnimation, RewardPointsAnimation, StackCardEmpty, FoxLoader have all been in production for 6+ months without this signature and are ruled out by age.

WalletHomeOnboardingSteps was introduced in PR #28851 (merged 2026-05-08), shipped first in release 7.79.0 (4532) — exactly the release Sentry first saw this crash in. It is the only new mount that landed in 7.79 and reached production users.

Repro steps (deterministic on debug build)

Fresh install of the app on an arm64 Android device or arm64 emulator. Complete primary onboarding through to the wallet home screen.

The wallet home onboarding checklist is visible (WalletHomeOnboardingSteps) with the checklist Rive animation playing.

Either:
a. Step through fund → trade → notifications using Skip/Continue, OR
b. Tap Primary on Trade or Notifications, get navigated away from wallet home, then return to wallet home.

Crash fires within ~1 second of returning to the wallet home / advancing.

Reproduces consistently on:

  • Pixel 9 Pro XL emulator (Android, arm64) — captured tombstone

  • Samsung Galaxy A32 (Android 13, arm64, physical device) — captured tombstone

Note: tested the production app on a flagship arm64 device, and the crash does NOT fire — instead the checklist animation blanks for ~0.25 seconds and recovers. Same underlying exception, non-fatal manifestation due to faster hardware / different runtime behavior. Implication: every user reaching this screen is hitting the bug; only some see the crash, the rest see a brief visual stall.

Diagnostic evidence

Full tombstone captured locally. Abort message:

Abort message: 'JNI DETECTED ERROR IN APPLICATION: JNI NewStringUTF called with pending exception java.lang.Throwable:
app.rive.runtime.kotlin.core.errors.StateMachineInputException: No StateMachineInput found with name Main.
    app.rive.runtime.kotlin.core.StateMachineInstance.input(StateMachineInstance.kt:139)
    app.rive.runtime.kotlin.controllers.RiveFileController.processAllInputs(RiveFileController.kt:678)
    app.rive.runtime.kotlin.controllers.RiveFileController.advance(RiveFileController.kt:328)
    app.rive.runtime.kotlin.renderers.RiveArtboardRenderer.advance(RiveArtboardRenderer.kt:88)
(Throwable with empty stack trace)
    in call to NewStringUTF'

Depending on the path that triggers it, the exception names a different missing input — observed both No StateMachineInput found with name Main. and No StateMachineInput found with name Outro. from the same screen on different runs.

Top native frames (same on every captured tombstone):

#00 abort
#01 art::Runtime::Abort
#08 art::CheckJNI::NewStringUTF
#09 rive_android::MakeJString
#11 rive_android::RiveLogD
#12 rive_android::DetachThread
#13 rive_android::JNIExceptionHandler::check_and_rethrow   <-- same as Sentry top frame
#14 rive_android::JNIExceptionHandler::CallVoidMethod
#15 rive_android::CanvasWorkerImpl::flush
#16 rive_android::WorkerImpl::doFrame
#17 rive_android::WorkerThread::threadMain

What is happening, step by step:

The state machine on the wallet home checklist Rive throws StateMachineInputException during RiveFileController.advance — runtime cannot find an input whose name the code passed to fireState.

The rive-react-native Android JNI layer catches the exception but then proceeds to make additional JNI calls (for thread detach + logging via RiveLogD → MakeJString → NewStringUTF) without first clearing the pending Java exception.

ART's CheckJNI / pending-exception checks detect this rules violation and abort the process (SIGABRT). On production builds without CheckJNI, the same path tends to fault inside check_and_rethrow itself, producing the SIGSEGV Sentry classifies.

Inspection of app/animations/onboard_checklist_v05.riv

The .riv file has three artboards (01_Add_Funds, 02_First_Trade, 03_Notifications), each with its own State Machine 1. The code calls fireState('State Machine 1', 'Main') and fireState('State Machine 1', 'Outro') against the active artboard depending on lifecycle (intro / outro / deferred-nav-return).

Opening the file in the Rive editor and expanding the State Machine inputs panel on each artboard shows the inputs are not consistent across the three artboards. The author has direct evidence (screenshots, captured tombstones, behavioral repro) tying the missing/inconsistent inputs to the specific fireState calls that crash. Sharing redacted detail in comments rather than the description so that the implementer can verify the findings themselves rather than anchoring on a single proposed fix.

Why timing lines up

WalletHomeOnboardingSteps introduced in PR #28851, merged 2026-05-08.

Crash signature first seen 2026-05-21, in release 7.79.0 (4532).

Feature-flag (homeTMCU610AbtestWalletHomePostOnboardingSteps) hit RC at 50% on 2026-05-18 and production at 25% on 2026-05-25, matching the Sentry event ramp.

No other consumer in 7.79 production is new; the rest have been in prod 6+ months without this signature.

Affected file paths

app/components/UI/WalletHomeOnboardingSteps/WalletHomeOnboardingSteps.tsx

app/components/UI/WalletHomeOnboardingSteps/walletHomeOnboardingChecklistRive.ts

app/animations/onboard_checklist_v05.riv

Package: rive-react-native@^9.8.0 (package.json:545)

Capture artifacts

Local tombstones, logcat traces, breadcrumb logs, and Rive editor screenshots available on request. Sentry issue (METAMASK-MOBILE-5VF9) has the original symbolicated stack for production events.

Acceptance criteria

The wallet home onboarding checklist flow no longer crashes the app on arm64 Android (both emulator and physical device).

Sentry METAMASK-MOBILE-5VF9 event rate drops to ~0 in the next production release that contains the fix.

No visual regression on the checklist Rive animation across all three steps and all entry / exit paths (Skip, Primary→navigate-away→return, last-step completion).

Links

Sentry: https://metamask.sentry.io/issues/7497101471/

Original PR that introduced WalletHomeOnboardingSteps: #28851

Feature flag: homeTMCU610AbtestWalletHomePostOnboardingSteps

Upstream library: https://github.com/rive-app/rive-react-native

Expected behavior

No response

Screenshots/Recordings

No response

Steps to reproduce

  1. Fresh install of the app on an arm64 Android device or arm64 emulator. Complete primary onboarding through to the wallet home screen.

  2. The wallet home onboarding checklist is visible (WalletHomeOnboardingSteps) with the checklist Rive animation playing.

Either:
a. Step through fund → trade → notifications using Skip/Continue, OR
b. Tap Primary on Trade or Notifications, get navigated away from wallet home, then return to wallet home.

Crash fires within ~1 second of returning to the wallet home / advancing.

Error messages or log output

Abort message: 'JNI DETECTED ERROR IN APPLICATION: JNI NewStringUTF called with pending exception java.lang.Throwable:
app.rive.runtime.kotlin.core.errors.StateMachineInputException: No StateMachineInput found with name Main.
    app.rive.runtime.kotlin.core.StateMachineInstance.input(StateMachineInstance.kt:139)
    app.rive.runtime.kotlin.controllers.RiveFileController.processAllInputs(RiveFileController.kt:678)
    app.rive.runtime.kotlin.controllers.RiveFileController.advance(RiveFileController.kt:328)
    app.rive.runtime.kotlin.renderers.RiveArtboardRenderer.advance(RiveArtboardRenderer.kt:88)
(Throwable with empty stack trace)
    in call to NewStringUTF'

Where was this bug found?

Live version (from official store)

Version

7.81

Build number

4823

Build type

None

Device

Android

Operating system

Android

Additional context

No response

Severity

No response

Metadata

Metadata

Assignees

Labels

Sev1needs-triageIssue needs to be triagedregression-prod-*Regression bug that was found in production in release *release-7.82.0Issue or pull request that will be included in release 7.82.0ta-ai-fixableTriage-Agent - Applied to small, well-scoped, non-security issuesta-needs-engineer-escalationTriage-Agent - Applied when confidence is below thresholdta-triagedteam-onboardingOnboarding teamtype-bugSomething isn't working

Type

No fields configured for Bug.

Projects

Status
To be triaged

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions