Skip to content
Latchkey

Node "bad interpreter" - Fix CRLF Shebang in a bin Script in CI

A shebang line with Windows CRLF endings makes the kernel read the interpreter as node\r (node plus a carriage return). On Linux CI that interpreter does not exist, so the script fails with a confusing "bad interpreter" / "No such file or directory" - even though node is installed.

What this error means

Executing a bin script fails with /usr/bin/env: ‘node\r’: No such file or directory (or bad interpreter). It typically appears after a file was authored or checked out with CRLF endings and then run on Linux.

Terminal
$ ./scripts/build.js
/usr/bin/env: 'node\r': No such file or directory
# the shebang line ends with \r\n, so the interpreter is "node\r"

Common causes

CRLF line endings on the shebang line

A file saved with Windows CRLF carries a trailing \r on the shebang. The loader treats node\r as the interpreter name, which does not exist on Linux.

Git re-introducing CRLF on checkout

A misconfigured core.autocrlf or a .gitattributes gap can check out script files with CRLF in CI even if they are LF in the repo.

How to fix it

Convert the script to LF endings

Strip the carriage returns and keep the file LF-only.

Terminal / .gitattributes
# fix the file
sed -i 's/\r$//' scripts/build.js
# enforce LF for scripts via .gitattributes
echo '*.js text eol=lf' >> .gitattributes
echo 'bin/* text eol=lf' >> .gitattributes

Stop CRLF at the source

  1. Set .gitattributes to force LF for shell/JS bin scripts.
  2. Configure editors to save scripts as LF.
  3. Avoid core.autocrlf=true for files that must stay LF.

How to prevent it

  • Force LF for executable scripts via .gitattributes.
  • Save bin scripts with LF endings.
  • Keep shebang lines free of trailing carriage returns.

Related guides

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