You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
dsh web crashes at startup on Nix-built Node binaries (nixpkgs nodejs / nodejs-slim) with:
Error: failed to apply loader entry <id> (@deepseek-ai/cordis-plugin-hmr): --expose-internals is required for HMR service
Three independent factors combine here: a bundle-level HMR disable that gets bypassed, a hard failure in the HMR constructor, and a native-addon fallback that only recognizes official Node builds.
Node: v24.18.0 and v26.5.0, both from nixpkgs (nodejs-slim, source-built)
OS: NixOS, x86_64
Not logged in any special way; plain npx @deepseek-ai/dsh web
What happens
$ npx @deepseek-ai/dsh web
dsh web: http://127.0.0.1:3080
Error: failed to apply loader entry 665a4325 (@deepseek-ai/cordis-plugin-hmr): --expose-internals is required for HMR service
...
[cause]: Error: --expose-internals is required for HMR service
at new Hmr (.../cordis-plugin-hmr/lib/index.js:107:40)
Process exits; the web UI never becomes usable.
Root cause analysis
1. runProfile force-recreates the HMR entry that dsh-web-app explicitly disables.
@deepseek-ai/dsh-web-app/cordis.patch.yml:
# TODO: Re-enable shared HMR for Web after its reload lifecycle is tested.
- id: hmrdisabled: true
But the CLI boot path (profile-boot, runProfile) only checks whether the hmrservice exists, and creates a fresh @deepseek-ai/cordis-plugin-hmr entry when it doesn't — ignoring that the bundle just disabled it on purpose:
2. The HMR constructor hard-fails without internal module access (cordis-plugin-hmr/lib/index.js:107):
if(!this.ctx.loader.internal)thrownewError("--expose-internals is required for HMR service");
Upstream cordis (@cordisjs/loader) treats loader.internal as optional and degrades gracefully; the vendored @deepseek-ai/cordis-plugin-loader acquires it eagerly via --expose-internals or the native addon.
3. The flag-free fallback (node-addon-require-builtin) fails on non-official Node builds.
Its runtime machine-code pattern matching does not recognize the accessor layout of Nix-built binaries:
node-addon-require-builtin unsupported:
Unsupported/no-getter (x64 sysv getter is not a recognized this->field accessor)
Verified test matrix (same addon version, same probe requireBuiltin('internal/modules/esm/loader')):
Node binary
Version
Source
Probe result
nixpkgs nodejs-slim
24.18.0
source-built
❌ Unsupported/no-getter
nixpkgs nodejs-slim
26.5.0
source-built
❌ Unsupported/no-getter
nodejs.org tarball
24.18.0
official
✅
So on Nix-built Node both paths to loader.internal are dead, and the crash in (2) fires. Note Node also rejects NODE_OPTIONS=--expose-internals, so there is no env-var workaround either.
Suggested fixes (any of these would help; 1 + 2 together would fix the crash path)
Graceful degradation: when loader.internal is unavailable, log a warning ("HMR disabled: no internal module access") and skip HMR instead of throwing — HMR is a dev convenience, not a precondition for dsh web to serve.
Respect the bundle disable: runProfile should check whether an hmr entry exists and is disabled (the dsh-web-app TODO case) rather than only checking service presence.
Optionally: teach node-addon-require-builtin to recognize Nix-built Node layouts, or document the --expose-internals workaround for source-built/distro Node in the README.
Workaround
alias dsh='node --expose-internals /path/to/node_modules/.bin/dsh'
Works reliably on every Node build since it uses the official flag path instead of machine-code probing. (Mentioning here for other Nix/distro-Node users who hit the same wall.)
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
dsh webcrashes at startup on Nix-built Node binaries (nixpkgsnodejs/nodejs-slim) with:Three independent factors combine here: a bundle-level HMR disable that gets bypassed, a hard failure in the HMR constructor, and a native-addon fallback that only recognizes official Node builds.
Environment
@deepseek-ai/dsh@0.1.0-rc.6(npx, standalone~/node_modulesinstall)nodejs-slim, source-built)npx @deepseek-ai/dsh webWhat happens
Process exits; the web UI never becomes usable.
Root cause analysis
1.
runProfileforce-recreates the HMR entry thatdsh-web-appexplicitly disables.@deepseek-ai/dsh-web-app/cordis.patch.yml:But the CLI boot path (
profile-boot,runProfile) only checks whether thehmrservice exists, and creates a fresh@deepseek-ai/cordis-plugin-hmrentry when it doesn't — ignoring that the bundle just disabled it on purpose:2. The HMR constructor hard-fails without internal module access (
cordis-plugin-hmr/lib/index.js:107):Upstream cordis (
@cordisjs/loader) treatsloader.internalas optional and degrades gracefully; the vendored@deepseek-ai/cordis-plugin-loaderacquires it eagerly via--expose-internalsor the native addon.3. The flag-free fallback (
node-addon-require-builtin) fails on non-official Node builds.Its runtime machine-code pattern matching does not recognize the accessor layout of Nix-built binaries:
Verified test matrix (same addon version, same probe
requireBuiltin('internal/modules/esm/loader')):Unsupported/no-getterUnsupported/no-getterSo on Nix-built Node both paths to
loader.internalare dead, and the crash in (2) fires. Note Node also rejectsNODE_OPTIONS=--expose-internals, so there is no env-var workaround either.Suggested fixes (any of these would help; 1 + 2 together would fix the crash path)
loader.internalis unavailable, log a warning ("HMR disabled: no internal module access") and skip HMR instead of throwing — HMR is a dev convenience, not a precondition fordsh webto serve.runProfileshould check whether anhmrentry exists and is disabled (thedsh-web-appTODO case) rather than only checking service presence.node-addon-require-builtinto recognize Nix-built Node layouts, or document the--expose-internalsworkaround for source-built/distro Node in the README.Workaround
Works reliably on every Node build since it uses the official flag path instead of machine-code probing. (Mentioning here for other Nix/distro-Node users who hit the same wall.)
All reactions