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

  1. 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.
  2. 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.
  3. Verify npm_config_platform/os/arch env vars or .npmrc overrides are not forcing a cross-platform install; unset them and reinstall.
  4. 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

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


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/045192dd5c8bc888. Report an issue: GitHub.