Skip to content

fix: Mark react-native-nitro-modules peer dependency as optional - #1516

Merged
mrousavy merged 1 commit into
mainfrom
fix/optional-nitro-peer
Aug 20, 2026
Merged

fix: Mark react-native-nitro-modules peer dependency as optional#1516
mrousavy merged 1 commit into
mainfrom
fix/optional-nitro-peer

Conversation

@mrousavy

Copy link
Copy Markdown
Member

Problem

Semver ranges never match pre-release versions unless a comparator shares the same major.minor.patch tuple and carries a pre-release tag. So the "react-native-nitro-modules": "*" peer range that every Nitro Module declares does not match 0.37.0-beta.0:

range 0.36.5 0.37.0-beta.0 0.37.0 0.38.0-beta.0
* yes no yes no
>=0.0.0-0 yes no yes no
>=0.37.0-0 no yes yes no

Because the peer is required, bun tries to satisfy it itself and installs a second, stable copy of react-native-nitro-modules nested inside the library. The native build then links the pre-release while Metro bundles the stable JS, and Nitro's own version guard throws at startup:

Nitro was installed twice: once with native version 0.37.0-beta.0 and once with JS version 0.36.5.

This is exactly what happened when upgrading react-native-nitro-image to the 0.37 beta (mrousavy/react-native-nitro-image#166) - builds stayed green, only the runtime harness tests caught it.

Fix

Mark the peer as optional. No range can express "anything, including future pre-releases" (see the table - >=0.37.0-0 just moves the breakage to 0.38.0-beta.0), so the fix has to be resolution behaviour rather than a cleverer range.

"peerDependenciesMeta": {
  "react-native-nitro-modules": { "optional": true }
}

Verified with a minimal repro: bumping an existing lockfile to a pre-release keeps a stale stable copy with a required peer, and resolves to a single copy with an optional one.

Applied to packages/template (so create-nitro-module and the docs' manual setup produce it), plus the two test libraries.

Trade-off

optional: true also suppresses the missing peer warning. That's an acceptable loss here: a Nitro Module without react-native-nitro-modules fails loudly at build time (autolinking can't find the pod / Gradle project), and version mismatches are already caught by Nitro's runtime guard - which is strictly stronger than an install-time range check.

Docs

  • how-to-build-a-nitro-module: documents the optional peer as part of library setup, with a warning explaining why.
  • troubleshooting: new Nitro was installed twice section covering diagnosis (npm ls), the real fix, the overrides/resolutions workaround for app authors stuck on a library that hasn't updated, and the reminder that package managers leave the stale copy on disk after the lockfile is fixed.

Note npm is unaffected - it special-cases * and accepts the pre-release. This is bun-specific behaviour.

Semver ranges never match pre-releases, so a required peer of "*" does
not match e.g. 0.37.0-beta.0. Package managers then install a second,
stable copy of Nitro next to the pre-release, and the native/JS version
guard throws "Nitro was installed twice" at runtime.

Marking the peer optional stops the package manager from resolving Nitro
on the library's behalf, leaving the app in full control of the version.
@vercel

vercel Bot commented Aug 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nitro-docs Ready Ready Preview Aug 20, 2026 4:12pm

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 682bfc9745

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +91 to +93
"overrides": {
"react-native-nitro-modules": "0.37.0-beta.0"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use an npm-compatible override for the direct dependency

When the app installed the beta normally, npm records a direct dependency such as "react-native-nitro-modules": "^0.37.0-beta.0"; npm 11.4.2 rejects the shown exact-version override before resolution with EOVERRIDE: Override for react-native-nitro-modules@^0.37.0-beta.0 conflicts with direct dependency. Consequently, npm users cannot complete this recovery procedure. Use an override referencing the direct dependency (for example $react-native-nitro-modules) or instruct users to make the direct dependency and override specifications identical.

Useful? React with 👍 / 👎.

npm install nitrogen --save-dev
```

Also declare `react-native-nitro-modules` as an **optional peer dependency**, so the app using your library is the one that decides which Nitro version gets installed:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Update the package README with the optional-peer metadata

The published packages/react-native-nitro-modules/README.md still tells library authors to add only the required "react-native-nitro-modules": "*" peer (lines 25–37). Authors following the npm/GitHub landing-page instructions instead of this Docusaurus page will therefore continue producing packages that trigger the duplicate installation under Bun with a Nitro prerelease, recreating the exact runtime failure this change is intended to prevent.

Useful? React with 👍 / 👎.

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