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

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 ""/bin/sh: Bad substitution""?
The sh step uses POSIX /bin/sh. Bash-specific features (case modification, here-strings, arrays) are not valid in dash and fail.
How do I fix "/bin/sh: Bad substitution"?
Invoke bash explicitly

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card