bash: /bin/bash^M: Bad Interpreter — Windows Line Endings

A script saved with Windows CRLF line endings embeds a literal carriage return in the shebang: the kernel looks for /bin/bash^M, which doesn't exist. Convert the file and fix git so it never happens again.

What you'll see

Root causes

CRLF line endings in the file

git's core.autocrlf=true on Windows, or a Windows editor, wrote . The shebang line /bin/bash makes the kernel search for an interpreter named bash plus a carriage return. cat -A shows the ^M characters immediately.

Fix it

  1. Confirm the CRLF contamination
    cat -A script.sh | head -3   # ^M at line ends = CRLF
  2. Convert the file
    sed -i 's/
    $//' script.sh   # or: dos2unix script.sh
  3. Fix git so it stops reintroducing them
    # .gitattributes in repo root: * text=auto eol=lf  — and *.sh specifically: *.sh text eol=lf
  4. Renormalize the repo once
    # git add --renormalize . && git commit -m 'normalize line endings'

Field note

The ^M in the error message IS the diagnosis — the interpreter path contains a carriage return, which can only come from a CRLF file. .gitattributes beats autocrlf settings for shared repos: it lives in the repo and normalizes every contributor identically, regardless of their local git config.

Common questions

Why do I see it in Docker builds but not locally?

The Windows checkout introduced the CRLF; Linux build containers faithfully copy it in. Developers on Linux/macOS with LF defaults never trigger it — a classic works-on-my-machine.

Does dos2unix change anything else?

It only strips CR characters at line ends (or converts as directed). Content, permissions, and everything else are untouched — safe on scripts, config files, and source.

Ship it right the first time

Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.

Browse the template store →

One-time. Yours to modify. Instant download from the NinjaOps template store.