SC2154: Referenced but Not Assigned Variables in Shell Scripts

Detect variables used without prior assignment. Learn how set -u, default values, and input validation prevent bugs from uninitialized variables.

ShellCheck Patterns

Detailed Explanation

Uninitialized Variable Bugs

Using a variable that was never assigned is one of the most common sources of bugs in shell scripts. Unlike most programming languages, bash does not raise an error for unset variables by default — they silently expand to empty strings.

The Silent Bug

# Typo in variable name
databse_url="postgres://..."
echo "$database_url"  # Empty! (typo: databse vs database)

# Forgotten assignment
if [ "$ENV" = "production" ]; then
  deploy_target="/opt/app"
fi
cd "$deploy_target"  # Empty if ENV != "production"!

Detection with set -u

#!/usr/bin/env bash
set -u

echo "$UNSET_VAR"
# bash: UNSET_VAR: unbound variable

This is the simplest and most effective guard. Add set -u at the top of every script.

Safe Default Values

When a variable might legitimately be unset, use parameter expansion:

# Use default if not set
log_level="${LOG_LEVEL:-info}"
port="${PORT:-3000}"
config_file="${CONFIG_FILE:-/etc/app/config.yml}"

Input Validation

For script arguments, validate early:

#!/usr/bin/env bash
set -euo pipefail

if [ $# -lt 2 ]; then
  echo "Usage: $0 <source> <destination>" >&2
  exit 1
fi

source_dir="$1"
dest_dir="$2"

Environment Variable Checks

# Require critical environment variables
: "${DATABASE_URL:?DATABASE_URL must be set}"
: "${API_KEY:?API_KEY is required}"
: "${DEPLOY_ENV:?DEPLOY_ENV not set (use: staging or production)}"

Common Patterns That Hide Bugs

# Conditional assignment without else
if condition; then
  var="value"
fi
echo "$var"  # Unset if condition was false!

# Fix: initialize with a default
var=""
if condition; then
  var="value"
fi

# Or use a ternary-like pattern
var=$(condition && echo "value" || echo "default")

The Difference Between Unset and Empty

var=""       # Set but empty
unset var    # Unset

# set -u catches only unset, not empty
set -u
echo "$var"  # OK if var="" (empty is fine)
echo "$var"  # Error if var is unset

Use Case

Debugging shell scripts with unexpected behavior, writing robust automation that handles edge cases, and enforcing variable initialization in team scripts. Particularly important for scripts that rely on environment variables.

Try It — Shell Script Linter

Open full tool