Skip to content
Latchkey

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.

Jenkins console
+ echo ${VERSION^^}
/home/jenkins/workspace/app@tmp/durable-abc/script.sh: 1: Bad substitution
script returned exit code 2

Diagnose it: agent, workspace, or sandbox?

Jenkinsfile
sh 'hostname && whoami && pwd'
sh 'java -version 2>&1'
sh 'env | sort | head -40'

// workspaces are reused between builds by default
cleanWs()

Common 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

  1. Use a bash shebang in a multi-line sh script, or call bash -c.
  2. Or rewrite the script in POSIX-compatible syntax.
  3. Confirm bash is installed on the agent.
Jenkinsfile
sh '''#!/usr/bin/env bash
set -euo pipefail
echo "${VERSION^^}"
'''

How to prevent it

  • Add a #!/usr/bin/env bash shebang when using bash-only features.
  • Lint shell with shellcheck against the intended shell.
  • Prefer POSIX syntax for portability across agents.

Frequently asked questions

What causes Jenkins sh "Bad substitution" (dash vs bash) in CI?
There are 2 common causes: bash-only syntax under dash and assuming bash is the default shell. The sh step uses POSIX /bin/sh.
How do I fix Jenkins sh "Bad substitution" (dash vs bash) in CI?
Invoke bash explicitly. Use a bash shebang in a multi-line sh script, or call bash -c.
What does Jenkins sh "Bad substitution" (dash vs bash) in CI actually mean?
A sh step fails with /bin/sh: 1: Bad substitution or Syntax error: ...
How do I stop Jenkins sh "Bad substitution" (dash vs bash) in CI happening again?
Add a #!/usr/bin/env bash shebang when using bash-only features. The prevention section lists 3 changes that keep it from recurring.

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