Jenkins sh "Bad substitution" (dash vs bash) in CI
The sh step runs the script with /bin/sh, which on Debian/Ubuntu agents is dash, not bash. Bash-only constructs (${var^^}, <<<, arrays, brace ranges) produce Bad substitution or a syntax error under dash.
What this error means
A sh step fails with /bin/sh: 1: Bad substitution or Syntax error: ... unexpected on a script that works in an interactive bash shell.
+ echo ${VERSION^^}
/home/jenkins/workspace/app@tmp/durable-abc/script.sh: 1: Bad substitution
script returned exit code 2Common causes
Bash-only syntax under dash
The sh step uses POSIX /bin/sh. Bash-specific features (case modification, here-strings, arrays) are not valid in dash and fail.
Assuming bash is the default shell
Scripts written and tested in bash break when the agent's /bin/sh is dash.
How to fix it
Invoke bash explicitly
- Use a bash shebang in a multi-line
shscript, or callbash -c. - Or rewrite the script in POSIX-compatible syntax.
- Confirm bash is installed on the agent.
sh '''#!/usr/bin/env bash
set -euo pipefail
echo "${VERSION^^}"
'''How to prevent it
- Add a
#!/usr/bin/env bashshebang when using bash-only features. - Lint shell with shellcheck against the intended shell.
- Prefer POSIX syntax for portability across agents.