Skip to content
Latchkey

Node "bad option" Unknown Flag in CI - Fix the Node Invocation

node: bad option means Node was launched with a flag it does not recognize, often a typo or a newer flag passed to an older Node in CI.

What this error means

A node invocation in CI exits immediately with node: bad option: <flag>, frequently because NODE_OPTIONS or the command line includes a flag the runner Node does not support.

node
node: bad option: --experimental-strip-types
$ exit status 9

Diagnose it: the shell in CI is not your shell

Package scripts run under a different shell, a different PATH, and a non-interactive environment on a runner. Most scripts that fail only in CI are relying on something the login shell gave them locally: a tool on PATH, an environment variable from a dotfile, or a TTY.

Terminal
# what the script can actually see
npm run env | grep -E "^(PATH|NODE_ENV|CI)=" 

# is the binary on PATH for the script, not just for you?
npm exec -- which <tool> || echo "not resolvable from npm scripts"

# run the exact script with tracing
sh -x -c "$(node -p "require('./package.json').scripts.build")"

Common causes

A flag newer than the CI Node version

A flag added in a later Node release is passed to an older runner Node that does not know it.

A typo in a flag or NODE_OPTIONS

A misspelled flag, or one Node does not allow in NODE_OPTIONS, is rejected as a bad option.

How to fix it

Pin a Node version that supports the flag

  1. Set the CI Node version to one that recognizes the flag.
  2. Re-run so the option is accepted.
GitHub Actions
- uses: actions/setup-node@v4
  with:
    node-version: 22

Fix or remove the flag

  1. Correct the flag spelling, or drop it if it is not needed.
  2. Confirm the flag is allowed in NODE_OPTIONS when set there.

Make failures fail the job

A multi-command script can report success while a middle command failed, which produces the worst kind of CI result: a green build that shipped something broken.

.github/workflows/ci.yml
# pipefail is NOT set by default in every runner shell
- name: Build
  shell: bash
  run: |
    set -euo pipefail
    npm run build | tee build.log

How to prevent it

  • Keep CI Node versions aligned with the flags your scripts need, validate NODE_OPTIONS contents, and only use flags the pinned Node version supports.

Frequently asked questions

What causes Node "bad option" unknown flag in CI?
There are 2 common causes: a flag newer than the ci node version and a typo in a flag or node_options. A flag added in a later Node release is passed to an older runner Node that does not know it.
How do I fix Node "bad option" unknown flag in CI?
There are 2 fixes depending on which cause you have: pin a node version that supports the flag and fix or remove the flag. Work through them in order, since the first is the most common.
What does Node "bad option" unknown flag in CI actually mean?
A node invocation in CI exits immediately with node: bad option: <flag>, frequently because NODE_OPTIONS or the command line includes a flag the runner Node does not support.
How do I stop Node "bad option" unknown flag in CI happening again?
Keep CI Node versions aligned with the flags your scripts need, validate NODE_OPTIONS contents, and only use flags the pinned Node version supports.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card