Skip to content
Latchkey

npm Script Fails on Shell Differences - Fix POSIX vs Windows in CI

npm runs scripts through a shell, and that shell differs by platform. A script using POSIX FOO=bar cmd inline env syntax works on Linux/macOS but breaks on a Windows runner’s default shell.

What this error means

A script that sets an env var inline (e.g. NODE_ENV=production webpack) passes on Linux CI but fails on a Windows runner with the variable "not recognized" or treated as a command. The reverse can happen with Windows-specific syntax on Linux.

npm output
> app@1.0.0 build
> NODE_ENV=production webpack

'NODE_ENV' is not recognized as an internal or external command,
operable program or batch file.
npm error code 1

Common causes

Inline POSIX env syntax on a non-POSIX shell

FOO=bar cmd is POSIX shell syntax. The default Windows shell does not understand it, so it treats NODE_ENV=... as a command and fails.

Shell operators that differ by platform

Quoting, path separators, and some operators behave differently across shells, so a script tuned for one platform breaks on another in a matrix build.

How to fix it

Set env vars cross-platform

Use cross-env (or the tool’s own config) so env vars work on every runner.

package.json
npm install --save-dev cross-env
// package.json
"scripts": {
  "build": "cross-env NODE_ENV=production webpack"
}

Avoid platform-specific shell features

  1. Prefer Node-based scripts over shell one-liners for cross-platform steps.
  2. Pin the shell in CI (e.g. set shell: bash on Windows runners) if you must use POSIX syntax.
  3. Keep path separators and quoting portable, or compute them in a Node script.

How to prevent it

  • Use cross-env for inline env vars in package.json scripts.
  • Prefer portable Node scripts over shell-specific one-liners.
  • Pin the shell explicitly in cross-platform CI matrices.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →