Skip to content

fix(install): desktop still gated on Node 26 by a stale lockfile engines mirror - #76575

Merged
OutThisLife merged 1 commit into
mainfrom
bb/desktop-lockfile-engines
Aug 2, 2026
Merged

fix(install): desktop still gated on Node 26 by a stale lockfile engines mirror#76575
OutThisLife merged 1 commit into
mainfrom
bb/desktop-lockfile-engines

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

hermes desktop still fails with EBADENGINE demanding Node >=26 after #76562 — my miss. I fixed apps/desktop/package.json but not its mirror in package-lock.json, and npm ci reads engines from the lockfile:

package.json  apps/desktop -> {'node': '^20.19.0 || >=22.12.0'}
package-lock  apps/desktop -> {'node': '>=26.0.0'}      <- what actually gated

Second problem, found while chasing that

The floor #76562 declared was too generous. Running the real npm ci over the whole workspace on Node 22.21.1:

npm error notsup Not compatible with your version of node/npm: react-router@8.3.0
npm error notsup Required: {"node":">=22.22.0"}

react-router 8.3.0 — a direct dependency of both apps/desktop and web — declares >=22.22.0. That is tighter than Vite's ^20.19 || >=22.12 and excludes all of Node 20. So >=20.0.0 promised support the tree cannot deliver: an install on Node 20 or early 22 cleared the installer's gate and then died inside npm ci on somebody else's package.

The fix

All four engine declarations now state the floor the dependency tree actually has, >=22.22.0 — root package.json, apps/desktop/package.json, and both package-lock.json mirrors. The installer gates move with them (node_satisfies_build, Test-NodeVersionOk) so a too-old system Node is replaced with the managed one before npm runs, and any failure a user does hit names hermes-agent instead of a transitive package. NODE_VERSION stays 22 — latest-v22.x is 22.23.2, comfortably above the floor.

Verification

Real npm ci --dry-run over the full workspace, not a trimmed fixture:

Node Result
22.23.2 (what install.sh provisions) ✓ 1258 packages
26.5.1 ✓ 1189 packages
22.21.1 (below the floor) ✓ EBADENGINE naming hermes-agent — our manifest, not react-router

The invariant test gains the case that would have caught the mirror drift on its own: the desktop assertion now pins the tightest floor any dependency actually declares, and the managed-runtime check compares majors, since install.sh fetches latest-v{major}.x rather than {major}.0.0.

Worth naming the lesson — I verified #76562 against a hand-built fixture (root manifest + lockfile only) rather than the real workspace tree. That fixture had no apps/desktop entry and no react-router, so it could not have caught either bug. The checks here run against git archive of the actual tree.

`hermes desktop` still failed with EBADENGINE demanding Node >=26 after
#76562, on a machine whose `apps/desktop/package.json` already said
`^20.19.0 || >=22.12.0`. #76562 fixed the manifest but not its mirror in
`package-lock.json`, and `npm ci` reads engines from the lockfile:

    package.json  apps/desktop -> {'node': '^20.19.0 || >=22.12.0'}
    package-lock  apps/desktop -> {'node': '>=26.0.0'}      <- what gated

Chasing that exposed a second, pre-existing problem: the floor #76562
declared was too generous. Running the real `npm ci` against the whole
workspace on Node 22.21.1 fails on a transitive dependency —

    npm error notsup Not compatible with your version of node/npm:
      react-router@8.3.0
    npm error notsup Required: {"node":">=22.22.0"}

react-router 8.3.0 (a direct dependency of both `apps/desktop` and `web`)
declares `>=22.22.0`, which is tighter than Vite's `^20.19 || >=22.12` and
excludes all of Node 20. So `>=20.0.0` promised support the tree cannot
deliver: an install on Node 20 or early 22 passed the installer's gate and
then died inside `npm ci` on someone else's package.

All four engine declarations now state the floor the dependency tree
actually has, `>=22.22.0`: root `package.json`, `apps/desktop/package.json`,
and both of their `package-lock.json` mirrors. The installer gates move with
them (`node_satisfies_build` in install.sh, `Test-NodeVersionOk` in
install.ps1) so a too-old system Node is replaced with the managed one
*before* npm runs, and the failure a user does see names hermes-agent rather
than a transitive package. NODE_VERSION stays 22 — latest-v22.x is 22.23.2,
comfortably above the floor.

The invariant test gains the case that would have caught the mirror drift on
its own: the desktop assertion now pins the tightest floor a dependency
actually declares, and the managed-runtime check compares majors, since
install.sh fetches latest-v{major}.x rather than {major}.0.0.

Verified with real `npm ci --dry-run` over the full workspace:
- node 22.23.2 (what install.sh provisions) -> 1258 packages
- node 26.5.1                               -> 1189 packages
- node 22.21.1 (below the floor)            -> EBADENGINE naming
  hermes-agent, i.e. our own manifest, not react-router
@OutThisLife
OutThisLife requested a review from a team August 2, 2026 04:28
@OutThisLife
OutThisLife merged commit 927662e into main Aug 2, 2026
42 of 43 checks passed
@OutThisLife
OutThisLife deleted the bb/desktop-lockfile-engines branch August 2, 2026 04:32
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 63ff4b8

ℹ️ Info

Desktop E2E visual evidence · View test artifacts · View job

3 visual diffs.

inline evidence is publishing...

@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/cli CLI entry point, hermes_cli/, setup wizard comp/desktop Electron desktop app (apps/desktop/*) area/install-update Installer, updater, packaging, wheels, doctor sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 2, 2026
teknium1 added a commit that referenced this pull request Aug 2, 2026
…ines churn (#76627)

The Playwright suite fails identically on every PR regardless of diff
(verified on a Python-only PR and a docs-only PR): the mock-backend
Electron window never gets a title, so boot/chat/setup/interim specs all
fail; only the dead-backend boot-failure path still passes. Breakage
window matches the Aug 1 night engines/npm churn (#76499/#76562/#76575).

Gated with 'false &&' in the job condition — delete that to re-enable.
Root-fix + re-enable tracked in #76627 (Ari).
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…ckfile-engines

fix(install): desktop still gated on Node 26 by a stale lockfile engines mirror
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…ines churn (NousResearch#76627)

The Playwright suite fails identically on every PR regardless of diff
(verified on a Python-only PR and a docs-only PR): the mock-backend
Electron window never gets a title, so boot/chat/setup/interim specs all
fail; only the dead-backend boot-failure path still passes. Breakage
window matches the Aug 1 night engines/npm churn (NousResearch#76499/NousResearch#76562/NousResearch#76575).

Gated with 'false &&' in the job condition — delete that to re-enable.
Root-fix + re-enable tracked in NousResearch#76627 (Ari).
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
…ckfile-engines

fix(install): desktop still gated on Node 26 by a stale lockfile engines mirror
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/install-update Installer, updater, packaging, wheels, doctor comp/cli CLI entry point, hermes_cli/, setup wizard comp/desktop Electron desktop app (apps/desktop/*) P1 High — major feature broken, no workaround sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants