fix(cli): skip compile cache on early Node 24.x to avoid startup deadlock - #89799
#89799fix(cli): skip compile cache on early Node 24.x to avoid startup deadlock#89799vincentkoc merged 6 commits intoopenclaw:mainopenclaw/openclaw:mainfrom zhangguiping-xydt:feat/issue-86550zhangguiping-xydt/openclaw:feat/issue-86550Copy head branch name to clipboard
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 15, 2026, 5:27 AM ET / 09:27 UTC. Summary PR surface: Source +38, Tests +241, Other +18. Total +297 across 4 files. Reproducibility: yes. from source and linked issue context, but not independently reproduced in this read-only pass. Current main enables packaged compile cache before CLI import, and the linked issue gives concrete Windows npm-global Node 24.1 steps for commands that hang before output. Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this narrow startup-boundary fix if maintainers accept the Windows Node 24.0-24.14 cutoff and the supplied native Windows packed-CLI proof; otherwise adjust the protected Windows range before merge. Do we have a high-confidence way to reproduce the issue? Yes from source and linked issue context, but not independently reproduced in this read-only pass. Current main enables packaged compile cache before CLI import, and the linked issue gives concrete Windows npm-global Node 24.1 steps for commands that hang before output. Is this the best way to solve the issue? Yes, conditionally: this is the best available fix shape because it touches both pre-import startup entry points and keeps unaffected runtimes enabled. The only remaining solution-fit question is maintainer acceptance of the Node 24.15 cutoff rather than the code layer. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 233b48daaab4. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +38, Tests +241, Other +18. Total +297 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
The mitigation makes sense, but I want to flag one scope question for maintainers: the issue description here is specifically Windows npm-global installs, while the guard disables compile cache for all Node 24.0–24.14 environments. That broader blast radius may still be the right tradeoff for now, but if the repro really is limited to Windows/global-install topology, it might be worth considering whether the skip can be narrowed so macOS/Linux users on those Node minors don’t lose compile-cache performance unnecessarily. |
6f2bb2b to
5761118
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Maintainer verification on exact head
Known gap: upstream Node release notes do not identify the OpenClaw-specific deadlock cutoff. The 24.15 boundary is supported by direct native Windows comparison proof. |
|
Superseding maintainer verification on final exact head
Known gap: upstream Node release notes do not identify the OpenClaw-specific deadlock cutoff. The 24.15 boundary is supported by direct native Windows comparison proof. |
…lock Node 24.0-24.14 enableCompileCache() can deadlock the ESM module loader on Windows npm-global installs, causing CLI to hang at startup. The release CI pins 24.15+ where this is not reproducible. Skip compile cache for Node 24.x < 24.15. Once users upgrade, the cache re-enables automatically. Fixes openclaw#86550
|
Merged via squash.
Thanks @zhangguiping-xydt! |
Summary
Disable Node compile cache for Windows packaged startup on early Node 24.x versions (
24.0-24.14), including the case where the packaged launcher or entry helper inheritsNODE_COMPILE_CACHEfrom the parent environment.This applies the same no-cache startup boundary to both the TypeScript packaged entry decision and the
openclaw.mjspackaged launcher path, while keeping compile cache enabled for non-Windows packaged installs on Node24.0-24.14, for Windows packaged installs on Node24.15+, and for other Node majors.This update also fixes the focused compile-cache regression test so its "unaffected packaged install" case explicitly runs as Linux Node 24.1 instead of inheriting the native Windows Node 24.1 proof runner environment.
Fixes #86550
Maintainer-ready summary
openclaw --version,openclaw doctor --fix --non-interactive,openclaw gateway start) produce output or exit. This patch removes the startup-level compile-cache trigger for that Windows/Node range while preserving compile-cache behavior outside that boundary.24.15+re-enable boundary. The previous evidence gap is now closed with native Windows side-by-side proof using the same packed OpenClaw artifact onnode@24.14.0andnode@24.15.0.24.0-24.14takes the protected no-cache path; Windows Node24.15+keeps compile cache enabled.Real behavior proof
24.0-24.14, including inheritedNODE_COMPILE_CACHE.563dcf592ec695bf34cf7fd4ba9aee141843fe6a, isolated npm-global prefixes, isolated OpenClaw home/state/config paths, inheritedNODE_COMPILE_CACHE, and explicit proof ports (19114for Node 24.14,19115for Node 24.15).npm packproducedopenclaw-2026.6.2.tgz; that same packed artifact was installed and tested under bothnode@24.14.0andnode@24.15.0.node@24.14.0 node_modules/vitest/vitest.mjs run src/entry.compile-cache.test.ts;node@24.15.0 node_modules/vitest/vitest.mjs run src/entry.compile-cache.test.ts;scripts/build-all.mjs;npm pack;npm install -g --prefix <isolated-prefix> openclaw-2026.6.2.tgzfor each runtime; with inheritedNODE_COMPILE_CACHE, runopenclaw --versionandopenclaw gateway install/start/status/stop/uninstall --jsonfor both Node 24.14 and Node 24.15; instrumentopenclaw.mjs gateway status --jsonwith--import compile-cache-proof-logger.mjsto capture the actual process/env transition.node@24.14.0andnode@24.15.0; the current PR head built and packed successfully; the same packed tarball installed in isolated npm-global prefixes under both runtimes;openclaw --versionand gateway install/start/status/stop/uninstall completed successfully for both runtimes; instrumentation showed Node 24.14 takes the no-cache respawn path while Node 24.15 keeps compile cache enabled through the packaged cache path.node@24.14.0andnode@24.15.0; build and pack completed; the same packed artifact installed in isolated npm-global prefixes under both runtimes; both runtime proof scripts completedopenclaw --versionand gateway install/start/status/stop/uninstall withPROOF_RC=0and gateway RPCok: true; the Node 24.14 process log proves the no-cache respawn (NODE_DISABLE_COMPILE_CACHE=1,OPENCLAW_COMPILE_CACHE_DISABLED_RESPAWNED=1, inheritedNODE_COMPILE_CACHEremoved); the Node 24.15 process log proves compile cache remains enabled by repointingNODE_COMPILE_CACHEto the packaged OpenClaw cache path, without the no-cache respawn marker.doctor --fix --non-interactivecomparison attempt as passing proof because it timed out after printing normal doctor output. Full-filetest/openclaw-launcher.e2e.test.tswas previously attempted under native Windows Node 24.1 but is not cited as passing proof due unrelated local fixture/runtime behavior.Current-head validation
node@24.14.0:node_modules/vitest/vitest.mjs run src/entry.compile-cache.test.tspassed 19/19 focused tests.node@24.15.0:node_modules/vitest/vitest.mjs run src/entry.compile-cache.test.tspassed 19/19 focused tests.scripts/build-all.mjscompleted successfully before packing the current PR artifact.npm packgeneratedopenclaw-2026.6.2.tgzfor the native comparison proof.node@24.14.0andnode@24.15.0.Native Windows side-by-side cutoff proof
24.14.0affected side: With inheritedNODE_COMPILE_CACHE, the instrumented process log shows the launcher respawned into the protected no-cache path: the child process hadNODE_DISABLE_COMPILE_CACHE=1,OPENCLAW_COMPILE_CACHE_DISABLED_RESPAWNED=1, and no inheritedNODE_COMPILE_CACHE. The packed CLI then completedopenclaw --versionandgateway install/start/status/stop/uninstall --jsonsuccessfully; gateway status showed the listener running and RPCok: true. The proof script exitedPROOF_RC=0.24.15.0re-enabled side: With inheritedNODE_COMPILE_CACHE, the instrumented process log shows the launcher did not take the no-cache respawn path. Instead, it kept compile cache enabled and repointedNODE_COMPILE_CACHEto the packaged OpenClaw cache directory (.../openclaw/2026.6.2/...), with noNODE_DISABLE_COMPILE_CACHEand noOPENCLAW_COMPILE_CACHE_DISABLED_RESPAWNED. The packed CLI then completedopenclaw --versionandgateway install/start/status/stop/uninstall --jsonsuccessfully; gateway status showed the listener running and RPCok: true. The proof script exitedPROOF_RC=0.Public evidence summary
The validation is summarized here as maintainer-readable commands and observed outcomes, not as local artifact paths:
Focused startup-decision regression test
node_modules/vitest/vitest.mjs run src/entry.compile-cache.test.tsnode@24.14.0: 19/19 tests passed.node@24.15.0: 19/19 tests passed.24.0-24.14disables compile cache / no-cache respawns when inherited cache is active; Windows Node24.15+keeps compile cache enabled; non-Windows Node24.0-24.14keeps compile cache enabled.Same packed artifact tested on both runtimes
scripts/build-all.mjscompleted.npm packproducedopenclaw-2026.6.2.tgz.node@24.14.0andnode@24.15.0.Native Windows packed CLI/gateway lifecycle
openclaw --version, thenopenclaw gateway install --json,gateway start --json,gateway status --json,gateway stop --json,gateway uninstall --json.24.14.0: proof script endedPROOF_RC=0; gateway status showed listener127.0.0.1:19114, server version2026.6.2, and RPCok: true.24.15.0: proof script endedPROOF_RC=0; gateway status showed listener127.0.0.1:19115, server version2026.6.2, and RPCok: true.Instrumented compile-cache behavior at the cutoff
24.14.0started with inheritedNODE_COMPILE_CACHE, then respawned withNODE_DISABLE_COMPILE_CACHE=1andOPENCLAW_COMPILE_CACHE_DISABLED_RESPAWNED=1; inheritedNODE_COMPILE_CACHEwas removed before the CLI import path.24.15.0started with inheritedNODE_COMPILE_CACHE, did not setNODE_DISABLE_COMPILE_CACHE, did not setOPENCLAW_COMPILE_CACHE_DISABLED_RESPAWNED, and continued withNODE_COMPILE_CACHEpointed at the packaged OpenClaw cache directory underopenclaw/2026.6.2/....This is why the final scope is narrow: protect Windows packaged startup on Node
24.0-24.14, while keeping compile cache enabled for non-Windows installs and Windows Node24.15+.What was not claimed
nodejs/node#60971); the direct reason to keep24.15+enabled in this PR is now the native Windows side-by-side OpenClaw proof above.doctor --fix --non-interactivecomparison attempt as passing proof because that command timed out after printing normal doctor output. The current-head native comparison proof instead usesopenclaw --versionand the gateway lifecycle, both of which completed withPROOF_RC=0for Node 24.14 and Node 24.15.test/openclaw-launcher.e2e.test.tswas previously attempted under native Windows Node 24.1 but is not cited as passing proof because local Windows fixture/runtime behavior caused unrelated failures; the source boundary is covered by the focused regression test plus packed CLI proof.Review findings addressed
24.14.0takes the no-cache respawn path; Windows Node24.15.0keeps compile cache enabled through the packaged cache path.24.0-24.14; non-Windows packaged installs and Windows Node24.15+keep compile cache enabled.24.14/24.15boundary.Regression Test Plan
src/entry.compile-cache.test.ts; launcher startup behavior is additionally covered by native packed npm-global proof.NODE_COMPILE_CACHEtriggers a one-shot no-cache respawn for affected Windows packaged startup; compile cache stays enabled for early Node 24.x on Linux/macOS packaged startup and for Node24.15+/ Node 22 / Node 25 on Windows packaged startup.nodeVersionandplatformdirectly proves the decision boundary, while the native npm-global proof covers the reported Windows packaged-startup class and the exact cutoff behavior.Root Cause
24.0-24.14and respawns affected packaged startup whenNODE_COMPILE_CACHEwas inherited, settingNODE_DISABLE_COMPILE_CACHE=1and removingNODE_COMPILE_CACHEbefore the runtime entry import. That removes the reported entry-level deadlock trigger for the affected Windows packaged startup class while preserving the existing compile-cache contract outside that boundary.Scope and architecture
24.0-24.14; unrelated CLI startup hangs remain out of scope.src/entry.compile-cache.tsis the canonical typed entry helper, andopenclaw.mjsis the canonical packaged launcher pre-import compile-cache path. Both now apply the same Windows Node24.0-24.14contract before callingenableCompileCache(...), inheriting compile cache, or respawning for packaged compile cache.check-upstream-fixedreported currentorigin/maindoes not already cover this PR.Patch quality notes
24.0-24.14, where inherited compile cache can preserve the startup hang. The default for every other packaged runtime remains the existing compile-cache-enabled path. The addedreturn falsebranches are explicit guard exits for unavailable/malformed version input or already-disabled compile-cache state; they are not silent product fallbacks and they preserve the previous default behavior outside the affected boundary. No new dependencies, config knobs, fallback stacks, or runtime shims were added.Merge risk
merge-risk: availability,merge-risk: compatibility.24.14/24.15cutoff behaves as intended.