Skip to content

fix(mobile): pin react-native-worklets and reanimated to the SDK 57 bundled versions - #119

Merged
toruiwasa merged 1 commit into
mainfrom
fix/mobile-worklets-version-pin
Sep 4, 2026
Merged

fix(mobile): pin react-native-worklets and reanimated to the SDK 57 bundled versions#119
toruiwasa merged 1 commit into
mainfrom
fix/mobile-worklets-version-pin

Conversation

@toruiwasa

Copy link
Copy Markdown
Owner

Closes #117

The first native build of apps/mobile ever attempted failed to compile. One error:

expo-modules-core/ios/WorkletsAdapter/ExpoWorkletsBridgeProvider.mm:236:19
no member named 'executeSync' in 'worklets::WorkletRuntime'

Root cause

expo/bundledNativeModules.json fixes the versions Expo SDK 57 supports:

Package SDK 57 expects Was resolved to
react-native-worklets 0.10.1 0.12.1
react-native-reanimated 4.5.1 4.6.0

Neither is a direct dependency. expo-router declares reanimated as a bare * peer and nothing pins worklets at all, so pnpm resolved the newest satisfying versions. expo-modules-core is written against the <=0.10 worklets API, and executeSync was removed in 0.12.

expo-modules-core states the constraint correctly — react-native-worklets: ^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0 — but declares the peer optional, so pnpm installs the mismatch with a warning instead of an error.

Why overrides and not just a dependency entry

Both. apps/mobile now declares them, because a package should say what it links — the rule from #97 and the same reasoning that added react-native-nitro-modules in #110. But that alone does not fix it: expo-modules-autolinking resolves native modules out of the pnpm store, and @expo/ui and expo-router still bound the 0.12.x copy. Only the workspace-level override removes it from the tree.

After the change pnpm why react-native-worklets reports 0.10.1 alone, and pnpm peers check no longer lists it as unmet.

The override carries the condition for lifting it: both pins move together, and only when bundledNativeModules.json for the SDK in use names newer versions. Pinning below what pnpm would pick otherwise holds the tree back silently.

Why CI did not catch it

Nothing in CI compiles native code. jest, tsc and eslint all passed on main throughout — they never touch Objective-C++. This bug was reachable only by running a native build by hand, which had never happened before. Filed as #118, deliberately not fixed here: choosing between a full macOS build job, a cheaper prebuild + pod install, and a per-PR expo-doctor is a real trade-off that belongs in its own change.

Verification

Built and ran on the iOS simulator (iPhone 17 Pro, iOS 26.5):

  • ExpoWorkletsBridgeProvider.mm compiles, then libExpoModulesWorkletsAdapter.a links — the exact file that failed before
  • Build Succeeded, app installs on the simulator
  • Metro bundles expo-router/entry.js (1347 modules) and the app renders

The Task 7 smoke screen reports both workspace packages resolved. Its @pulseticker/logging line asserts sanitize({access_token}).access_token === '[REDACTED]', so this run also exercises the sanitize() rewrite from #110 at runtime on a device, which until now had only unit-test coverage.

pnpm build   6/6
pnpm test    6/6

Pods confirmed re-resolved: RNReanimated (4.5.1), RNWorklets (0.10.1), alongside NitroMmkv (4.3.2) and NitroModules (0.37.0).

Not verified: Android. The same override applies, but no Android build was run — expo-system-ui (#113) is the other Android-only gap still open.

🤖 Generated with Claude Code

…undled versions

The first native build of apps/mobile failed to compile. One error:

  ExpoWorkletsBridgeProvider.mm:236
  no member named 'executeSync' in 'worklets::WorkletRuntime'

expo/bundledNativeModules.json fixes react-native-worklets at 0.10.1 and
react-native-reanimated at 4.5.1, but neither is a direct dependency —
expo-router declares reanimated as a bare `*` peer and nothing pins worklets —
so pnpm resolved the newest satisfying versions, 0.12.1 and 4.6.0.
expo-modules-core is written against the <=0.10 worklets API, and 0.12 removed
executeSync. Its peer range states the constraint correctly, but the peer is
optional, so pnpm installs the mismatch with a warning rather than an error.

The pins go in pnpm-workspace.yaml overrides, not only in apps/mobile's
dependencies. Declaring them in the app is necessary — it should say what it
links — but not sufficient: expo-modules-autolinking resolves native modules
out of the store, and @expo/ui and expo-router still bound the 0.12.x copy.
With the override the tree holds 0.10.1 and 4.5.1 alone and pnpm peers check
is clean.

Nothing in CI caught this because nothing in CI compiles native code — jest,
tsc and eslint all passed throughout. That gap is filed as #118.

Verified by building and running on the iOS simulator: ExpoWorkletsBridgeProvider.mm
compiles, Build Succeeded, the app installs, Metro bundles 1347 modules, and the
Task 7 smoke screen reports both workspace packages resolved — which also
exercises the sanitize() rewrite from #110 at runtime. pnpm build 6/6,
pnpm test 6/6.

Closes #117

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NfHB8Q3zSQ5idotURDwkyv
@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pulseticker Ready Ready Preview Sep 3, 2026 4:57am UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS native build fails: react-native-worklets floats to 0.12.x, outside expo-modules-core's API

1 participant