Skip to content

Skip -base-bytecode when Hermes bytecode versions differ - #57

Merged
ashirman merged 2 commits into
mainfrom
fix/hermes-base-bytecode-version
Oct 8, 2026
Merged

ashirman merged 2 commits into
mainfrom
fix/hermes-base-bytecode-version

Conversation

@revopushbot

Copy link
Copy Markdown
Contributor

Problem

A customer's release-react failed with:

Error deserializing base bytecode: Wrong bytecode version. Expected 98 but got 96

When Hermes is enabled, the CLI downloads the base release bundle for the deployment and app version and passes it to the local compiler as hermesc -base-bytecode <file>. hermesc refuses any base whose bytecode version differs from its own. In this case the base was v96 and the local compiler produces v98, after a React Native / Hermes upgrade.

Fix

  • Read the base bundle's bytecode version from its file header. Every Hermes version, from v0.1.0 to static_h (Hermes V1), starts the file with uint64 magic (0x1F1903C103BC1FC6) followed by uint32 version, little-endian. This is the same field the Hermes loader checks when it raises "Wrong bytecode version".
  • Read the compiler's version from hermesc -version, which prints HBC bytecode version: N. Old compilers print the same line.
  • Keep -base-bytecode only when the two versions match. When they differ, when the compiler version can't be detected, or when the base isn't Hermes bytecode, drop the flag and log why. The base only makes the output smaller to diff, so the release still works without it.

The mismatch warning also says that apps built with the older bytecode can't run the new update. If React Native was upgraded, the customer needs a new store build.

Also fixed (found in review)

  • Failed compile: the hermes exit handler now stops after reporting a failure, so a failed compile no longer copies its partial .hbc over the JS bundle.
  • Source map step: the same early return was added to the source map handler.
  • Missing compiler: a wrong hermesc path now fails the release with an error instead of crashing the CLI.
  • Version check: hermesc -version now has a 30-second timeout.

Open question

On a version mismatch the release still uploads, with a warning. We could instead fail the release unless --force is passed, since devices on the older binary can't load the bundle.

Testing

  • New test/hermes-bytecode.ts covers reading the header, plain JS and truncated files, parsing the -version output, and keeping or skipping the base.
  • Checked against a real hermesc (v96): compiling a file and reading its header gives 96, and parsing -version gives 96.
  • tsc passes, and all 26 tests pass (hermes-bytecode, release-size-flow, release-size-utils, source-map-utils).

🤖 Generated with Claude Code

revopushbot and others added 2 commits October 9, 2026 00:30
hermesc aborts with "Wrong bytecode version. Expected N but got M" when
the base release bundle was compiled by a different Hermes bytecode
version (e.g. v96 base vs v98 compiler after a React Native upgrade).
Read the version from the base bundle's HBC header and from
`hermesc -version`, and drop -base-bytecode with a warning when they
differ, cannot be detected, or the base is not Hermes bytecode.

Also stop the hermes and compose-source-maps close handlers after
rejecting, reject on hermes spawn errors, and time out the version probe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compile an empty input to stdout with `hermesc -emit-binary -` and read
the version from the emitted header instead of parsing `hermesc -version`
text, so the base bundle and the compiler are checked the same way.
Shorten the version mismatch warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ashirman
ashirman merged commit 5accbf7 into main Oct 8, 2026
2 checks passed
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.

2 participants