NousResearch/hermes-agent · critical · Error
[stage-native-deps] get-windows binding ${dir}/node-get-wind
Error message
[stage-native-deps] get-windows binding ${dir}/node-get-windows.node: expected ${platform}, got ${classified ?? 'unknown'}. Refusing to stage a binary compiled for the wrong platform. What it means
Thrown by the desktop app's native-dependency staging build script (apps/desktop/scripts/stage-native-deps.mjs) after copying a prebuilt get-windows N-API binding into the staged output. The script classifies the staged .node binary's target platform (via classifyNativeBinary, which inspects PE/Mach-O/ELF headers) and compares it to the platform it is staging for. A mismatch means the node_modules cache or checkout contains a binding compiled for a different OS/arch than the current build target, and staging a wrong-platform binary would produce a runtime 'Invalid ELF class'/'%1 is not a valid Win32 application'-style crash later.
Source
Thrown at apps/desktop/scripts/stage-native-deps.mjs:515
rebuild()
bindingDirs = scanBindingDirs()
}
if (bindingDirs.length === 0) {
throw new Error(
'[stage-native-deps] get-windows has no win32 prebuilt binding under lib/binding. ' +
'Recover from the checkout root with:\n' +
' npm install-scripts approve get-windows\n' +
' npm rebuild get-windows'
)
}
for (const dir of bindingDirs) {
const dest = join(destRoot, 'lib', 'binding', dir)
mkdirSync(dest, { recursive: true })
const destFile = join(dest, 'node-get-windows.node')
cpSync(join(bindingRoot, dir, 'node-get-windows.node'), destFile)
const classified = classifyNativeBinary(destFile)
if (classified !== platform) {
throw new Error(
`[stage-native-deps] get-windows binding ${dir}/node-get-windows.node: ` +
`expected ${platform}, got ${classified ?? 'unknown'}. ` +
'Refusing to stage a binary compiled for the wrong platform.'
)
}
}
}
console.log(`[stage-native-deps] staged get-windows (${platform}) -> ${destRoot}`)
return destRoot
}
function rebuildGetWindowsViaNpm() {
const result = spawnSync('npm', ['rebuild', 'get-windows'], {
cwd: resolve(projectRoot, '..', '..'),
stdio: 'inherit',
// npm resolves to npm.cmd on Windows, which needs a shell.
shell: process.platform === 'win32'View on GitHub (pinned to c896c09c42)
Solutions
- Delete node_modules and the get-windows prebuild cache, then reinstall: `rm -rf node_modules && npm install` so bindings are fetched/built for the current platform.
- If the prebuilt binary came from a `npm rebuild get-windows` on another OS, run the recovery printed just above the throw: `npm install-scripts approve get-windows && npm rebuild get-windows` from the checkout root.
- Verify npm_config_platform/os/arch env vars or .npmrc overrides are not forcing a cross-platform install; unset them and reinstall.
- On CI, key the node_modules cache on runner OS+arch so a linux-built cache never lands on a win32 runner.
Example fix
# before (stale cross-platform node_modules) npm run build:desktop # -> [stage-native-deps] get-windows binding ... expected win32, got linux # after git clean -fdx apps/desktop rm -rf node_modules node_modules/get-windows npm install-scripts approve get-windows npm rebuild get-windows npm run build:desktop
Defensive patterns
Strategy: validation
Validate before calling
// Before staging, classify every binding and fail fast with a clear message
import { classifyNativeBinary } from './stage-native-deps.mjs'
for (const dir of bindingDirs) {
const got = classifyNativeBinary(join(bindingRoot, dir, 'node-get-windows.node'))
if (got !== process.platform) {
console.error(`Skipping stage: ${dir} binding is ${got}, expected ${process.platform}. Run: npm rebuild get-windows`)
process.exit(1)
}
} Prevention
- Key node_modules caches on OS+arch in CI so cross-platform caches never mix
- Run `npm rebuild get-windows` after switching runner OS or arch
- Treat this throw as a hard build failure — never bypass the platform check to 'get the build green'
When it happens
Trigger: Running the stage script (or a desktop build that invokes it) when join(bindingRoot, dir, 'node-get-windows.node') is a binary for another platform/arch than the `platform` argument — e.g. switching between linux and win32 CI runners without a clean npm rebuild, restoring node_modules from a cache built on another OS, or cross-compiling with an env (npm_config_platform / --os) that disagrees with the prebuilt binaries present.
Common situations: CI cache poisoning (node_modules cached per-branch but shared across runner OSes), checking out on Windows after building on Linux (or vice versa), using a package cache/mirror that served the wrong prebuild, or running under Rosetta/emulation where arch (x64 vs arm64) detection diverges from the staged binaries.
Related errors
- Rebuilding the desktop app failed (exit {:?}). The update wa
- gh pr create failed (is gh installed and authenticated?)
- Branch name is required.
- Secure token storage is unavailable (no OS keyring service w
- Failed to encrypt the remote gateway token for secure storag
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/045192dd5c8bc888.
Report an issue: GitHub.