chore(deps): pin react-native-fs so Renovate dep PRs stop shipping a lockfile npm ci rejects - #40
Merged
Conversation
`harper > alasql` declares `react-native-fs` as an optionalDependency, and
`react-native-fs` has a required peer dependency on `react-native`. npm's
install resolver silently drops this optional subtree whenever it resolves
the tree from scratch (no existing entry carried forward in node_modules or
the lock) — it never even attempts to place it. But `npm ci`'s validator
computes an ideal tree that *does* include the subtree, then rejects any
lock that lacks it:
npm error code EUSAGE
npm error Missing: react-native-fs@2.20.0 from lock file
npm error Missing: react-native@0.84.1 from lock file
npm error Missing: react@19.2.8 from lock file
npm 11 (Node 24/26) enforces this; Node 22's older npm was lenient. Renovate
regenerates package-lock.json from scratch when it updates dependencies (its
raw output for PR #39 had the entire ~250-package react-native subtree
pruned, 1216 entries), so every dep PR shipped a lock its own `npm ci`
rejected and had to be regenerated by hand.
`skipInstalls: false` could not fix this: a full `npm install` from scratch
prunes the subtree identically to `npm install --package-lock-only` — the
prune is in the ideal-tree builder, not the reify step.
Declaring `react-native-fs` as a direct devDependency makes npm treat it as
required rather than optional, so it (and its react-native peer subtree) is
resolved consistently by both `npm install` and `npm ci`, and survives a
from-scratch regeneration. The package set and every version are unchanged
versus the previous lock (0 added, 0 removed, 0 version changes); the large
line delta is only the `"optional": true`/`"peer": true` flags being dropped
from the now-required subtree. It is a devDependency, so the published
package is unaffected. fsevents and every other platform-gated package stay
optional, so Linux CI still installs cleanly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
c5b68bb added `skipInstalls: false` to force Renovate into a full `npm install`, on the theory that `--package-lock-only` was what pruned the optional react-native-fs subtree. That theory was wrong: a full install prunes the subtree exactly the same way (the drop happens in npm's ideal-tree builder, before the reify step), so PR #39 still shipped a pruned lock with the override already in place. The real fix pins react-native-fs as a direct devDependency, which holds regardless of Renovate's install mode. Remove the override so Renovate returns to its faster default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request adds the react-native-fs dependency (version 2.20.0) to package.json and updates package-lock.json accordingly, which also removes the optional flag from numerous lockfile entries. Additionally, the skipInstalls configuration is removed from renovate.json. As there are no review comments, I have no feedback to provide.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every Renovate dependency PR shipped a
package-lock.jsonthatnpm cirejected on Node 24/26, requiring a manual lockfile regeneration each time (e.g. #39's fixup, and 55c5bba before it):Root cause
harper > alasqldeclaresreact-native-fsas an optionalDependency, andreact-native-fshas a required peer onreact-native. This trips a genuine npminstall/cidivergence:npm install(both--package-lock-onlyand a full install) silently drops the entire optional react-native subtree whenever it resolves the tree from scratch — it never even attempts to place it.npm cicomputes an ideal tree that still includes that subtree, then rejects any lock missing it. npm 11 (Node 24/26) enforces this; Node 22's older npm was lenient, which is why CI failed only on the newer matrix legs.Renovate regenerates the lockfile from scratch when it updates dependencies — its raw output for #39 had the whole ~250-package subtree pruned (1216 entries) — so the pruned lock landed on every dep PR.
Why
skipInstalls: false(c5b68bb) didn't helpThat change assumed
--package-lock-onlywas the culprit and forced a fullnpm install. But a full install from scratch prunes the subtree identically — the drop is in npm's ideal-tree builder, not the reify step — so #39 still shipped a pruned lock with the override already in place.Fix
Pin
react-native-fsas a direct devDependency. That makes npm treat it as required rather than optional, sonpm installandnpm ciresolve it identically and it survives a from-scratch regeneration. The now-redundant, disprovenskipInstalls: falseis removed so Renovate returns to its faster default."optional"/"peer"flags dropping off the now-required subtree.fseventsand every other platform-gated package stay optional, so Linux CI still installs cleanly.Verification
npm cion npm 11 (Node 24/26)npm cion npm 10 (Node 22)rm lock + node_modules) + harper bump →npm ciformat:check+ build + unit testsThe clean-room-regen-then-
npm citest faithfully simulates a future Renovate dep PR installing on Node 24/26.🤖 Generated with Claude Code