Skip to content

/errors/bash/unbound-variable

bash: NAME: unbound variable

verified onenvironmentlocal · linux 6.18.44-fc-v140 x64 · GNU bash 5.2.21updated
tool
Bash
exit code
1
versions
bash 4.x, bash 5.x
os
linux, macos, windows

NAME: unbound variable is printed by bash when the nounset option (set -u) is on and the script expands a variable that has never been set. bash stops the script instead of silently using an empty string. Give optional variables an explicit default with ${NAME:-default}, or check that required arguments were passed before using them.

Reproduce it

bash
cat > greet.sh <<'EOF'
set -u
echo "start"
echo "hello ${NAME}"
echo "never printed"
EOF
bash greet.sh
echo "exit status: $?"

Output

start
greet.sh: line 3: NAME: unbound variable
exit status: 1

The message names the script, the line and the variable, and the script stops with status 1. A missing positional parameter fails the same way:

bash
cat > first.sh <<'EOF'
set -u
echo "first argument: $1"
EOF
bash first.sh
echo "exit status: $?"

Output

first.sh: line 2: $1: unbound variable
exit status: 1

Fixes

bash
cat > greet.sh <<'EOF'
set -u
echo "hello ${NAME:-world}"
echo "optional: [${OPTIONAL:-}]"
if [[ -v NAME ]]; then echo "NAME is set"; else echo "NAME is not set"; fi
EOF
bash greet.sh
NAME=ada bash greet.sh

Output

hello world
optional: []
NAME is not set
hello ada
optional: []
NAME is set
ExpansionWhen NAME is unsetUse for
${NAME:-default}expands to defaultoptional settings
${NAME:-}expands to an empty stringoptional values that may be empty
${NAME:=default}assigns default, then expands itset once, reuse later
${NAME:?message}prints message and exitsrequired values with a clear error
${NAME+x}empty if unset, x if settesting whether NAME is set

Required arguments

bash
cat > copy.sh <<'EOF'
set -u
src=${1:?usage: copy.sh SOURCE}
echo "copying $src"
EOF
bash copy.sh
echo "exit status: $?"

Output

copy.sh: line 2: 1: usage: copy.sh SOURCE
exit status: 1

${1:?message} turns the generic error into a usage message and still exits with a non-zero status. "$@" never triggers the error, even with no arguments.

Sources