fix(update): provision a managed Node runtime when system npm fails engines.npm - #76464
Merged
Merged
Conversation
…ngines.npm The npm 12 requirement (f88ed6c) strands every system-Node install: no shipping Node bundles npm >=12, engine-strict makes EBADENGINE fatal, and the recovery in npm_engine.py refuses to touch a system npm — so 'hermes update' leaves the install in a mixed state (updated code, stale Node deps, no TUI/web/desktop rebuild) with only a manual-fix hint. Instead of modifying the user's toolchain (still never done), the EBADENGINE recovery now provisions Hermes' own managed Node tree under $HERMES_HOME/node — the same pinned-nodejs.org path install.sh and install.ps1 use — upgrades THAT npm into the required range, and hands the caller the managed npm for its single retry. - hermes_constants.bootstrap_hermes_managed_node(): cross-platform provisioning (POSIX via node-bootstrap.sh _nb_install_bundled_node, Windows via the existing portable-zip download); reuses a healthy tree. - node-bootstrap.sh: HERMES_NODE_SKIP_LINKS=1 skips the ~/.local/bin node/npm/npx symlinks so the private tree never shadows the user's own toolchain on PATH. - maybe_repair_npm_engine() now returns the npm path to retry with (managed-in-place upgrade or freshly provisioned runtime); both call sites retry with the returned path and put the managed tree first on PATH so npm lifecycle scripts resolve the managed node. - Node-only mismatches on a foreign npm are now also recoverable (the managed tree ships a supported Node); on a managed npm they still correctly decline. E2E (real download, temp HERMES_HOME): provisioned node v22.23.2, upgraded bundled npm 10.9.4 -> 12.0.2, system npm byte-identical after, no ~/.local/bin links re-pointed, healthy-tree reuse in 0.05s.
Contributor
૮ >ﻌ< ა ci reviewran on 38ec51b ℹ️ InfoDesktop E2E visual evidence · View test artifacts · View job3 visual diffs. inline evidence upload failed. Failed to upload diff-1508682a2ae8-boot-ready-diff.png with gh image (exit code 1): Error uploading /home/runner/work/_temp/e2e-evidence/diff-1508682a2ae8-boot-ready-diff.png: step 0 (get upload token): uploadToken not found on repo page — do you have write access to NousResearch/hermes-agent? (or, if NousResearch enforces SAML SSO, authorize at https://github.com/orgs/NousResearch/sso) |
This was referenced Aug 1, 2026
14 tasks
This was referenced Aug 2, 2026
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.
Summary
hermes updatenow recovers from EBADENGINE on system-Node installs by provisioning Hermes' own managed Node runtime instead of dead-ending with a manual-fix hint.Root cause of the outage: f88ed6c set
engines.npm: ">=12.0.0"(correct — npm 11.10-11.x parsesmin-release-agebut ignoresmin-release-age-exclude, which would hard-fail the excluded fresh packages), but no shipping Node bundles npm 12 yet (Node 24.16 ships 11.13). Withengine-strict=true, every user on system Node failsnpm ci/npm install, and the existing recovery only upgrades a Hermes-managed npm — system npm got a hint and a mixed-state install (updated code, stale Node deps, no TUI/web/desktop rebuild). This is what hit emozilla (#75598 is the same incident shape).Changes
hermes_constants.py: newbootstrap_hermes_managed_node()— cross-platform managed-Node provisioning (POSIX:_nb_install_bundled_nodefromnode-bootstrap.sh, the same pinned-nodejs.org pathinstall.shuses; Windows: the existing portable-zip download from the heal path). Reuses a healthy managed tree when present.scripts/lib/node-bootstrap.sh:HERMES_NODE_SKIP_LINKS=1skips the~/.local/binnode/npm/npx symlinks so the recovery-provisioned tree never shadows the user's own toolchain on PATH.hermes_cli/npm_engine.py:maybe_repair_npm_engine()now returns the npm path to retry with — the same npm after an in-place managed upgrade, or a freshly provisioned managed npm when the failing npm is foreign (system/nvm/brew/Nix — still never modified). Node-only mismatches on a foreign npm are now recoverable too (the managed tree ships a supported Node); the fresh tree's bundled npm is upgraded intoengines.npmrange so the retry can't fail identically.hermes_cli/main.py: both call sites (_run_npm_install_deterministic, TUI install) retry with the returned npm and put the managed tree first on PATH so npm lifecycle scripts resolve the managed node.tests/hermes_cli/test_npm_engine.py: updated contract + new coverage for foreign-npm provisioning, failed-bootstrap fallback to the manual hint, and both Node-only mismatch shapes.Validation
engines.npm: >=12~/.local/binlinksE2E with a real download into a temp
HERMES_HOMEagainst Jeff's verbatim error output: provisioned node v22.23.2, upgraded bundled npm 10.9.4 → 12.0.2, fake system npm untouched. Targeted tests: 20/20test_npm_engine.py, 68/68test_cmd_update.py+test_hermes_constants.py, 36/36 web-ui/desktop/gui suites.Infographic