Skip to content

fix(ios): align expo module set to SDK 57.0.8 and gate dyld symbols - #425

Closed
RonenMars wants to merge 1 commit into
integration-merge-354-355-376from
fix/expo-sdk-57-version-skew
Closed

fix(ios): align expo module set to SDK 57.0.8 and gate dyld symbols#425
RonenMars wants to merge 1 commit into
integration-merge-354-355-376from
fix/expo-sdk-57-version-skew

Conversation

@RonenMars

Copy link
Copy Markdown
Owner

Summary

TestFlight build 173 crashed at launch on every device with EXC_CRASH (SIGABRT) / Termination Reason: DYLD 4 Symbol missing.
ExpoCamera 57.0.1 referenced AnyModule._decorateExpoObject(object:in:appContext:), but the bundled ExpoModulesCore 57.0.7 renamed that protocol requirement to the two-argument _decorateModule(object:in:), so dyld aborted before any app code ran.

The skew came from #412, which pinned expo-modules-core forward to 57.0.7 via npm overrides to get ColorCompat for the Android R8 minify step, without moving the rest of the Expo module set with it.
ExpoModulesCore ships as a precompiled xcframework, so the mismatch was invisible at compile time and surfaced only in dyld — which is why CI went green and the iOS ship job succeeded.
The third item on #412's own test plan ("Smoke-check iOS build still links after ExpoModulesCore 57.0.7 pod bump") is the one that would have caught it.

Changes

  • Bump expo to 57.0.8 and align all 22 expo-* / @expo/* modules to that SDK's bundled native module set.
    That supplies expo-modules-core 57.0.7 legitimately and moves expo-camera to 57.0.3.
  • Remove the now-redundant expo-modules-core override.
    The Android ColorCompat fix from fix(android): pin expo-modules-core for R8 ColorCompat #412 is preserved because core still resolves to 57.0.7.
  • Bump react-native-screens to 4.26.2 to match what expo-router 57.0.8 requires, removing a duplicate nested copy.
  • expo-image-manipulator was still on 57.0.1 and referenced the same missing symbol, so a first pass that only fixed expo-camera was incomplete.

Guardrails

  • scripts/verify-dyld-symbols.sh resolves every cross-framework symbol in the exported archive before the altool upload, so a launch-crashing build cannot reach TestFlight.
    It runs in both the local and CI ship paths via archive-and-upload.sh.
  • npm run check:native-deps (new Native deps CI job) fails on duplicate native modules, which is the npm-level shape of this bug.

Both were validated in each direction: they pass on a good build and fail on the real defect.
The symbol check is what surfaced the expo-image-manipulator breakage.

Test plan

  • Release build for generic/platform=iOS succeeds
  • verify-dyld-symbols.sh reports all 637 cross-framework symbols resolving on that build
  • verify-dyld-symbols.sh fails when a bundled export is renamed (simulated 173 skew)
  • check:native-deps passes on the aligned tree and fails on a reintroduced duplicate
  • Unit tests: 95/95 suites, 897 tests pass
  • Typecheck: 3 errors, identical at base f2242bc4 — pre-existing, in files this PR does not touch
  • Integration tests: 4 failed / 35 passed, identical at base f2242bc4 — pre-existing
  • Deploy iOS from this branch and confirm the build launches from TestFlight

Notes

react-native-get-random-values sits at 2.0.0 while SDK 57.0.8 wants ~1.11.0.
Left as-is: it is a deliberate pin from #332, is not ABI-coupled to expo-modules-core, and the Release build links clean.
The lockfile regeneration surfaced that pre-existing drift rather than introducing it.

Dependabot #415 (expo-image-picker → 57.0.6), #414 (expo-font → 57.0.1), and #353 (shell-quote → 1.10.0) are subsumed by this branch and can be closed.
#413 (babel-preset-expo) and #291 (typescript 7) are unaffected and still stand on their own.

Build 173 should be pulled from TestFlight once a replacement is up.

Build 173 crashed at launch on every device with EXC_CRASH (SIGABRT) / "DYLD 4 Symbol missing": ExpoCamera 57.0.1 referenced AnyModule._decorateExpoObject(object:in:appContext:), but the bundled ExpoModulesCore 57.0.7 renamed that protocol requirement to the two-argument _decorateModule(object:in:).

The skew came from #412, which pinned expo-modules-core forward to 57.0.7 via npm overrides to get ColorCompat for the Android R8 minify step, without moving the rest of the Expo module set with it.
ExpoModulesCore ships as a precompiled xcframework, so the mismatch was invisible at compile time and only surfaced in dyld.

Bump expo to 57.0.8 and align all 22 expo-*/@expo/* modules to that SDK's bundled native module set, which supplies expo-modules-core 57.0.7 legitimately and moves expo-camera to 57.0.3.
The override is now redundant and is removed; the Android ColorCompat fix is preserved because core stays at 57.0.7.
Also bump react-native-screens to 4.26.2 to match what expo-router 57.0.8 requires, removing a duplicate nested copy.

expo-image-manipulator was still on 57.0.1 and referenced the same missing symbol, so the original fix was incomplete.

Add two guardrails, both verified against a real Release build:
- scripts/verify-dyld-symbols.sh resolves every cross-framework symbol in the archive before altool upload, so a launch-crashing build cannot reach TestFlight.
- npm run check:native-deps fails CI on duplicate native modules, which is the npm-level shape of this bug.
@RonenMars
RonenMars deleted the branch integration-merge-354-355-376 July 26, 2026 08:09
@RonenMars RonenMars closed this Jul 26, 2026
RonenMars added a commit that referenced this pull request Jul 26, 2026
The integration branch has never been run through test.yml, so three failures accumulated unnoticed across ~82 commits.
PR #425 was the first thing to trigger CI on it, which surfaced them.

Type check and Integration tests both traced to app/conversation/[id].tsx.
a1e263c added LivePauseControl to the header actions and, in resolving that conflict, deleted the in-chat search Pressable that ff28c60 had introduced, while leaving the MagnifyingGlass import, the headerButton styles, the searchBarState hook, and the test coverage all in place.
The same commit also dropped the makeSearchStyles import while keeping its call site, which is the TS2552 error.
Restore both: the import and the search button, verbatim from a1e263c's parent.

i18n unused keys flagged three keys with no remaining code reference.
b75dfb8 pruned connect.step1 and connect.step2 as dead, but ConnectStep.tsx still renders all three steps as a numbered sequence, so step3 rendered alone after a gap.
Restore step1 and step2 in all four locales from their pre-prune text.
Drop onboarding.connect.footnote and servers.dialog.removeDismiss, which are genuinely unreferenced.

conversation.search.open is left as-is: it labels the restored search button, so it was never dead.
RonenMars added a commit that referenced this pull request Jul 28, 2026
The integration branch has never been run through test.yml, so three failures accumulated unnoticed across ~82 commits.
PR #425 was the first thing to trigger CI on it, which surfaced them.

Type check and Integration tests both traced to app/conversation/[id].tsx.
a1e263c added LivePauseControl to the header actions and, in resolving that conflict, deleted the in-chat search Pressable that ff28c60 had introduced, while leaving the MagnifyingGlass import, the headerButton styles, the searchBarState hook, and the test coverage all in place.
The same commit also dropped the makeSearchStyles import while keeping its call site, which is the TS2552 error.
Restore both: the import and the search button, verbatim from a1e263c's parent.

i18n unused keys flagged three keys with no remaining code reference.
b75dfb8 pruned connect.step1 and connect.step2 as dead, but ConnectStep.tsx still renders all three steps as a numbered sequence, so step3 rendered alone after a gap.
Restore step1 and step2 in all four locales from their pre-prune text.
Drop onboarding.connect.footnote and servers.dialog.removeDismiss, which are genuinely unreferenced.

conversation.search.open is left as-is: it labels the restored search button, so it was never dead.
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.

1 participant