Files
Sauci/.agents/learnings/promoted/2026-08-31-expo-prebuild-native-regression.md
T
jjbruntonandClaude Fable 5 7a76936829 docs(agents): promote v1.0.8 release learnings
Record three confirmed v1.0.8 failure modes (expo prebuild native
regressions, npm 10/11 lockfile divergence, local EAS build
preconditions) and promote each into docs/releasing.md, a new
docs/development/dependencies.md, and the release-preflight script.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 16:03:02 +01:00

2.8 KiB

id, date, status, scope, evidence, destination, review_after
id date status scope evidence destination review_after
2026-08-31-expo-prebuild-native-regression 2026-08-31 promoted apps/mobile native projects (ios/, android/) and expo prebuild v1.0.8 SDK 54 to 56 upgrade, commits 604eec3, 7aca39a, 6bd04a6, 79233f5, b8cb2add apps/mobile/scripts/release-preflight.mjs, apps/mobile/scripts/release-preflight.test.mjs, and docs/releasing.md 2026-11-30

Symptom

expo prebuild --clean during the SDK 54 to 56 upgrade (and the @bacons/apple-targets 0.1 to 5.0 bump) silently regressed four checked-in native invariants. Each regression was caught only by a release gate or by manual diffing against the last shipped tag (3fc6f8a, v1.0.7), not by prebuild itself.

Reproduction

Run expo prebuild --clean in apps/mobile against the upgraded SDK and diff the regenerated ios/ and android/ projects against the previously committed projects.

Cause

  1. Widget identity: apple-targets 5.x derives PRODUCT_BUNDLE_IDENTIFIER from the target folder name, changing com.sauci.app.LiveDrawWidget to com.sauci.app.widget, and repointed CODE_SIGN_ENTITLEMENTS to the gitignored ios/.targets/LiveDrawWidget/generated.entitlements.
  2. Android manifest lost the tools:node="remove" attributes on READ_MEDIA_IMAGES and READ_MEDIA_VIDEO, so the built AAB regained Play-forbidden permissions (verified via bundletool dump on the rejected build 50 AAB).
  3. iOS Info.plist gained dev-launcher-only keys NSBonjourServices (_expo._tcp), NSLocalNetworkUsageDescription, and RCTMetroPort.
  4. android/gradle.properties reset to stock -Xmx2048m -XX:MaxMetaspaceSize=512m, causing Metaspace OOM in kspReleaseKotlin/CMake under RN 0.85.

Separately, a package absent from the new SDK's bundledNativeModules (expo-av) has no compatible release and fails the iOS archive (EXAV.h imports removed ExpoModulesCore headers).

Remediation

Fixed by restoring widget identity and tracking targets/widget/generated.entitlements with a pinned bundleIdentifier (604eec3); restoring manifest tools:node="remove" attributes (7aca39a); removing the dev-launcher-only Info.plist keys (6bd04a6); raising gradle.properties memory to 4096m/1024m (79233f5); and migrating expo-av to expo-video/expo-audio (b8cb2add).

Extend apps/mobile/scripts/release-preflight.mjs with executable checks for items 2 and 3 (item 1 is already covered by the existing LiveDrawWidget preflight check; item 4 hard-fails the build by itself). Add an "After native regeneration" checklist to docs/releasing.md.

Evidence

node apps/mobile/scripts/release-preflight.mjs fails if the tracked AndroidManifest.xml lacks tools:node="remove" on READ_MEDIA_IMAGES or READ_MEDIA_VIDEO, or if ios/Sauci/Info.plist contains NSBonjourServices, NSLocalNetworkUsageDescription, or RCTMetroPort. node --test apps/mobile/scripts/release-preflight.test.mjs covers the new checks.