Skip to content

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

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#4165
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 does not match a version like 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 satisfies it itself by installing a second, stable copy of react-native-nitro-modules nested inside this library. An app testing a Nitro pre-release then builds native against the pre-release while Metro bundles the stable JS, and Nitro throws at startup:

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

Builds stay green - only runtime catches it.

Fix

Mark the peer optional, so the consuming app is the sole decider of the Nitro version. No range can express "anything, including future pre-releases" (>=0.37.0-0 just moves the breakage to 0.38.0-beta.0), so this has to be resolution behaviour rather than a cleverer range.

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

Upstream fix in the Nitro template + docs: margelo/nitro#1516

Trade-off

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

The example app declares react-native-nitro-modules directly, so it is unaffected.

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 leaves the consuming app in full control of
the installed Nitro 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)
react-native-vision-camera-docs Ready Ready Preview Aug 20, 2026 4:13pm

Request Review

@mrousavy
mrousavy merged commit 98aef29 into main Aug 20, 2026
5 checks passed
@mrousavy
mrousavy deleted the fix/optional-nitro-peer branch August 20, 2026 16:14
mrousavy added a commit that referenced this pull request Aug 20, 2026
Superseded by #4165 - marking the peer dependency optional stops the
package manager from resolving a second, stable Nitro next to the
pre-release, so the root override is no longer needed.

Verified from a clean node_modules: exactly one Nitro copy
(0.37.0-beta.1) and `bun install --frozen-lockfile` passes.
mrousavy added a commit that referenced this pull request Aug 20, 2026
* feat: Upgrade Nitro to 0.37 for View improvements

* fix: Override `react-native-nitro-modules` to 0.37.0-beta.0

`*` in peerDependencies does not match prereleases, so bun could not
dedupe the peer onto the hoisted 0.37.0-beta.0 and installed a second
copy at 0.36.5 under each package. That auto-installed peer state also
broke `bun install --frozen-lockfile` in CI - the lockfile round-trips
byte-identically, so regenerating it never helped.

Pin it via a root override for now.

* feat: Upgrade Nitro to 0.37.0-beta.1

Regenerates specs with nitrogen 0.37.0-beta.1, which migrates the View
prop types from `CachedProp` to `ReactProp`.

beta.1 also re-adds legacy `CachedProp` as deprecated, so
`react-native-nitro-image@0.15.1` - whose generated code still uses
`CachedProp::isDirty`/`::value` - compiles again. That was what broke
Build Android on beta.0.

* fix: Drop `react-native-nitro-modules` override

Superseded by #4165 - marking the peer dependency optional stops the
package manager from resolving a second, stable Nitro next to the
pre-release, so the root override is no longer needed.

Verified from a clean node_modules: exactly one Nitro copy
(0.37.0-beta.1) and `bun install --frozen-lockfile` passes.

* feat: Upgrade Nitro to 0.37.0 and Nitro Image to 0.15.2

Nitro 0.37.0 and nitrogen 0.37.0 are now stable; nitrogen's generated
output is identical to 0.37.0-beta.1, so no spec changes were needed.

Nitro Image 0.15.2 is regenerated with nitrogen 0.37.0 (no more
deprecated `CachedProp`) and marks its `react-native-nitro-modules`
peer dependency as optional.
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