Variable is referenced but not assigned

SC2154 explained: variable is referenced but not assigned. Why the warning fires, how typos silently delete the wrong files, and how to fix it with `set -u`.

Problem

Bash treats unset variables as empty by default, so a typo silently becomes an empty string. `rm -rf "$user_home/.cache"` becomes `rm -rf "/.cache"` if `$user_home` was actually spelled `$userhome`. The script doesn't fail — it deletes the wrong thing.

Bad

dir="$HOMR/projects"   # typo: $HOMR
ls "$dir"               # silently lists "/projects" or nothing

Good

#!/usr/bin/env bash
set -u                  # fail on unset variables
dir="$HOME/projects"
ls "$dir"

# Or use the safer expansion form to provide a default / fail explicitly:
dir="${HOME:?HOME is unset}/projects"

Explanation

`set -u` (or `set -o nounset`) makes Bash exit when you reference an unset variable, surfacing typos immediately. The `${VAR:?message}` form fails per-use without changing global script behavior. Both are dramatically safer than the default.

Related

SC2155

SC2034

When It Matters

A referenced-but-never-assigned variable is either a typo or a dependency on something outside the file. Without set -u it expands to the empty string, so the script continues with a missing value and fails somewhere unrelated — an empty path in a delete, an empty host in a curl, an empty version tag in a release. The warning is most valuable in scripts that read configuration, where a renamed setting leaves references behind that never fail loudly.

Second Example

Note

The ${VAR:=default} form assigns a default in place, while ${VAR:?message} aborts with a clear message — together they document every external input at the top of the script.

Exceptions

Variables set by a sourced config file, exported by a parent process, or assigned indirectly through eval or printf -v are invisible to static analysis. Add a source directive so ShellCheck can follow the file, or disable the rule at the reference with a comment naming the origin.

Faq

Q

What is the difference between SC2154 and SC2153?

A

SC2154 means the variable is never assigned anywhere in the file. SC2153 is the narrower case where a similarly named variable is assigned, suggesting a typo.

Q

How do I declare that a variable comes from the environment?

A

Reference it once with a default or a required check at the top of the script. That both silences the warning and documents the contract.

Q

Does set -u break scripts that use optional variables?

A

It can, which is why optional values should be written as ${VAR:-default} rather than bare references.