Skip to content

Fix Hermes bytecode version mismatch in SwiftPM Release builds - #57928

Open
nduaarte wants to merge 1 commit into
react:mainfrom
nduaarte:fix/spm-hermes-bytecode-version-mismatch
Open

Fix Hermes bytecode version mismatch in SwiftPM Release builds#57928
nduaarte wants to merge 1 commit into
react:mainfrom
nduaarte:fix/spm-hermes-bytecode-version-mismatch

Conversation

@nduaarte

Copy link
Copy Markdown
Contributor

Summary:

react-native spm add's Release builds crash on launch with:

Compiling JS failed: Wrong bytecode version. Expected 99 but got 98

This happens because the SwiftPM integration resolves the Hermes runtime
(the downloaded hermes-engine.xcframework) and the Hermes compiler (the
hermesc binary that turns the JS bundle into bytecode) from two independent,
unsynced sources:

  • download-spm-artifacts.js's resolveHermesArtifact() picked the runtime
    by querying the hermes-compiler package's latest-v1 dist-tag on the npm
    registry live, at build time.
  • generate-spm-xcodeproj.js's resolveHermesCliPathSetting() (and
    react-native-xcode.sh, for the CocoaPods-free fallback) points
    HERMES_CLI_PATH at the hermes-compiler package already installed in
    this project's own node_modules
    — whatever got pinned the last time
    npm install ran.

If the latest-v1 dist-tag advances on npm between npm install and the
Release build (which happens routinely as new Hermes builds are published),
the downloaded VM and the locally pinned hermesc fall out of sync and the
app crashes at launch. react-native-xcode.sh already documents this exact
invariant ("react native pins the hermes-compiler version, so the compiler's
bytecode version always matches the prebuilt hermes VM artifacts") — SwiftPM's
artifact download just wasn't honoring it.

This PR makes resolveHermesArtifact() read the pinned hermes-compiler
version from node_modules first (the same require.resolve lookup already
used for HERMES_CLI_PATH), so the runtime download and the compiler always
agree. It falls back to the previous latest-v1 npm lookup only when
hermes-compiler isn't locally resolvable (e.g. USE_HERMES=false apps that
never installed it). Explicit HERMES_VERSION overrides (nightly,
latest-v1, a literal version) are unchanged.

Fixes #57917.

Changelog:

[IOS] [FIXED] - Fix Hermes runtime/compiler version mismatch causing "Wrong bytecode version" crashes in SwiftPM Release builds

Test Plan:

Added unit tests covering the new local-resolution path, the fallback when
hermes-compiler isn't installed, and confirming existing HERMES_VERSION
overrides still take precedence over the local pin.

$ node_modules/.bin/jest packages/react-native/scripts/spm/__tests__/download-spm-artifacts-test.js
Test Suites: 1 passed, 1 total
Tests:       70 passed, 70 total

$ node_modules/.bin/flow check packages/react-native/scripts/spm/download-spm-artifacts.js
No errors!

$ node_modules/.bin/eslint packages/react-native/scripts/spm/download-spm-artifacts.js packages/react-native/scripts/spm/__tests__/download-spm-artifacts-test.js
(no output — clean)

$ node_modules/.bin/prettier --check packages/react-native/scripts/spm/download-spm-artifacts.js packages/react-native/scripts/spm/__tests__/download-spm-artifacts-test.js
All matched files use Prettier code style!

Reproduced the crash and confirmed the fix end-to-end using the public
reproducer linked from the issue
(https://github.com/marandaneto/react-native-087-swiftpm-hermes-bytecode-repro):

  • Before the fix: npm run reproduce builds successfully but launching the
    app in the iOS Simulator crashes with Compiling JS failed: Wrong bytecode version. Expected 99 but got 98.
  • After applying the equivalent fix to the reproducer's installed
    react-native copy: the log shows Using locally pinned hermes-compiler: 250829098.0.16, and both the debug and release Hermes runtime artifacts
    resolve to that exact version — matching the hermesc used for
    HERMES_CLI_PATH. xcodebuild ... -configuration Release succeeds, and
    the app installs and launches cleanly on an iPhone 17 Pro (iOS 26.5)
    simulator with no crash.

download-spm-artifacts.js picked the Hermes runtime xcframework by
querying the hermes-compiler npm package's latest-v1 dist-tag live, at
build time. generate-spm-xcodeproj.js's HERMES_CLI_PATH resolution (and
react-native-xcode.sh's SwiftPM fallback) instead point at the
hermes-compiler package already pinned in the project's own
node_modules. When the live dist-tag advances between `npm install`
and a Release build, the two disagree and the app crashes at launch
with "Wrong bytecode version".

Make resolveHermesArtifact() read the pinned hermes-compiler version
from node_modules first, falling back to the latest-v1 lookup only
when the package isn't locally resolvable.

Fixes react#57917.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 12, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Aug 12, 2026

@cipolleschi cipolleschi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this.

@meta-codesync

meta-codesync Bot commented Aug 13, 2026

Copy link
Copy Markdown

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D115859923.

@cortinico cortinico left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review automatically exported from Phabricator review in Meta.

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[iOS][SwiftPM] 0.87 Release app crashes because Hermes compiler emits bytecode 98 but runtime expects 99

3 participants