MetaMask / MetaMask/metamask-mobile

CXX1210: Hermes prefab not found — reproducible build failure in v7.76.0 (RN 0.76.9 + New Architecture)

Open
#30,428 0 comments 0 reactions 0 assignees View on GitHub
external-contributor
Dominant language
TypeScript
Stars
3k
Forks
1.7k
Avg merge
1d 14h
Merged PRs (30d)
669

Description

### What is this about?

Hi MetaMask team!

We're from [WalletScrutiny](https://walletscrutiny.com), a project that verifies whether cryptocurrency wallets can be built reproducibly from source. We attempted to build MetaMask Android **v7.76.0** from source and ran into a consistent build failure we'd like to report and discuss.

## The Error

Every build attempt fails during Gradle's cmake configuration phase:

```
> Task :react-native:packages:react-native:ReactAndroid:configureCMakeRelWithDebInfo[arm64-v8a] FAILED

Caused by: com.android.builder.errors.EvalIssueException:
[CXX1210] .../node_modules/react-native/ReactAndroid/src/main/jni/CMakeLists.txt
release|arm64-v8a : No compatible library found
```

This happens for all four ABIs. The build takes ~20 minutes before failing (yarn install and repository setup complete successfully; the failure is at native CMake configuration).

## Root Cause Identified

After extensive diagnosis, we traced this to `.yarn/patches/react-native-patch-d76d50a92f.patch`, which MetaMask applies during `yarn install`. This patch modifies `ReactAndroid/build.gradle.kts` inside the `react-native` package:

```kotlin
// After MetaMask's Yarn patch is applied — ReactAndroid/build.gradle.kts line ~655:
// It's up to the consumer to decide if hermes should be included or not.
// Therefore hermes-engine is a compileOnly dependency.
compileOnly("com.facebook.react:hermes-android:0.76.9")
```

The problem: **AGP does not extract prefab packages for `compileOnly` dependencies in library modules.**

Prefab is the mechanism that allows cmake to find C/C++ libraries via `find_package()`. AGP only unpacks prefab content for `implementation`, `api`, and `runtimeOnly` configurations — not `compileOnly`. With hermes declared as `compileOnly` inside ReactAndroid (a library module), AGP never extracts the hermes AAR's prefab directory into the cmake search path (`.cxx/*/prefab/`), so cmake's `find_package(hermes-engine REQUIRED CONFIG)` finds nothing and throws CXX1210.

## Environment

| Component | Version |
|-----------|---------|
| MetaMask version | 7.76.0 (tag `v7.76.0`, commit `a9b520593aa735b2f5a8718887977e6a34128e62`) |
| React Native | 0.76.9 |
| Architecture | New Architecture (Fabric + TurboModules) |
| Android SDK | 35 |
| NDK | 26.1.10909125 |
| AGP | 8.6.0 (from Gradle wrapper) |
| Java | OpenJDK 17 |
| Build command | `./gradlew bundleProdRelease` |
| Host OS | Debian 12 Bookworm (Docker container) |

## Fix Attempted

We applied a sed patch after `yarn install` to change the dependency scope:

```bash
sed -i 's/compileOnly("com.facebook.react:hermes-android:/api("com.facebook.react:hermes-android:/' \
node_modules/react-native/ReactAndroid/build.gradle.kts
```

Diagnostic output confirmed the patch applied (`compileOnly` → `api` on line 657). In at least one run, this allowed cmake to proceed — the build reached `:app:bundleProdReleaseResources` before being interrupted. However, the fix was not stable across runs, suggesting an additional environmental factor we have not yet isolated.

We also tried adding `prefab = true` to the `buildFeatures {}` block in the same file, which is required for library modules to consume prefab packages in some AGP configurations.

## Questions for the MetaMask Team

1. **How does your Bitrise CI environment resolve hermes at the cmake level?** The Yarn patch comment says "It's up to the consumer to decide if hermes should be included or not." What does the "consumer" in your production build do to re-add hermes with the correct scope?

2. **Is there a `hermes-engine` dependency at the app module level** (in `android/app/build.gradle`) that your CI relies on, which forces AGP to extract the hermes prefab before ReactAndroid's cmake runs?

3. **Does your CI use `newArchEnabled=true` in `gradle.properties`?** We're using New Architecture as detected from the repository defaults — is the production build configuration different?

4. **Is there internal build documentation we may have missed?** We reviewed the README, CI YAML files, and `scripts/build.sh` but didn't find a guide for external reproducible builds.

## Context: WalletScrutiny Verification

We previously filed [a related issue for v7.61.6](https://github.com/MetaMask/metamask-mobile/issues) covering Boost/Hermes build failures. Since then, MetaMask upgraded to RN 0.76.9 with the New Architecture, and the failure mode shifted from Boost extraction to hermes prefab resolution. Progress has been made — the build now gets much further than before — but the CXX1210 issue is the remaining blocker.

We'll mark MetaMask v7.76.0 as `ftbfs` (failed to build from source) on WalletScrutiny until the build can be reproduced. We want MetaMask to succeed here — an open-source self-custody wallet that builds reproducibly is a strong security signal for users.

Any guidance on the expected build environment or how to replicate the consumer-level hermes setup would be very appreciated.

---

**WalletScrutiny:**
- Website: https://walletscrutiny.com
- MetaMask listing: https://walletscrutiny.com/android/io.metamask/
- Methodology: https://walletscrutiny.com/methodology/

### Scenario

_No response_

### Design

_No response_

### Technical Details

_No response_

### Threat Modeling Framework

_No response_

### Acceptance Criteria

_No response_

### Stakeholder review needed before the work gets merged

- [ ] Engineering (needed in most cases)
- [ ] Design
- [ ] Product
- [ ] QA (automation tests are required to pass before merging PRs but not all changes are covered by automation tests - please review if QA is needed beyond automation tests)
- [ ] Security
- [ ] Legal
- [ ] Marketing
- [ ] Management (please specify)
- [ ] Other (please specify)

### References

_No response_

Contributor guide

Open the contributing guide

Research direction

Reproduce ./gradlew bundleProdRelease with the listed environment, then inspect .yarn/patches/react-native-patch-d76d50a92f.patch and node_modules/react-native/ReactAndroid/build.gradle.kts around the hermes-android dependency. Check android/app/build.gradle, gradle.properties, and scripts/build.sh for consumer-level Hermes configuration. Done means a clean source build resolves Hermes prefab for all ABIs without manual edits.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, cmake, kotlin, react-native
Domain
build-system, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.