You log in to a fresh server and see warnings like these:
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LC_CTYPE = "UTF-8",
LANG = "en_US.UTF-8"
are supported and installed on your system.
The cause is almost always one of two things. Either the locale isn’t generated on the server, or your SSH client forwards your local machine’s locale, which the server doesn’t have. Here’s how to fix both.
What a locale is
A locale defines language and formatting: character encoding (UTF-8), date and number formats, sort order and message language. It’s controlled by environment variables:
| Variable | Controls |
|---|---|
LANG |
Default for everything |
LC_CTYPE, LC_TIME, LC_NUMERIC, … |
Individual categories |
LC_ALL |
Overrides everything (use for testing only) |
LANGUAGE |
Message language preference list |
Check yours:
locale
locale -a # locales available on this system
Fix 1: generate the locale
Debian / Ubuntu
sudo apt install locales
sudo locale-gen en_US.UTF-8
sudo update-locale LANG=en_US.UTF-8
Or choose interactively:
sudo dpkg-reconfigure locales
On Debian, locale-gen builds the locales enabled in /etc/locale.gen. Uncomment the line (en_US.UTF-8 UTF-8) and run sudo locale-gen.
RHEL, Rocky, AlmaLinux, Fedora
Locales come as language packs:
sudo dnf install glibc-langpack-en
sudo localectl set-locale LANG=en_US.UTF-8
Log out and back in to apply.
Fix 2: stop SSH from forwarding your local locale
macOS and many desktop Linux setups send LANG and LC_* through SSH. If your Mac uses de_DE.UTF-8 or the odd LC_CTYPE=UTF-8, the server tries to use it and complains.
Server side, you can stop accepting them. In /etc/ssh/sshd_config, comment out:
#AcceptEnv LANG LC_*
Then sudo systemctl reload ssh (or sshd).
Client side, you can stop sending them. In ~/.ssh/config on your computer, there’s no clean per-option switch, so the usual fix is in the system-wide client config (/etc/ssh/ssh_config). Comment out SendEnv LANG LC_*. On macOS, Terminal’s “Set locale environment variables on startup” option affects this too.
Alternatively, generate the locale your client sends (Fix 1). Then everything matches.
Set the system default with localectl
sudo localectl set-locale LANG=en_US.UTF-8
localectl status
This writes /etc/default/locale (Debian/Ubuntu) or /etc/locale.conf (RHEL).
C.UTF-8: the minimal choice
C.UTF-8 is built into modern glibc and is always available. It gives UTF-8 encoding with plain, byte-order (“C”) sorting and English messages. It’s a great default for servers and containers when you don’t need language-specific formatting:
sudo localectl set-locale LANG=C.UTF-8
In Dockerfiles:
ENV LANG=C.UTF-8
Why it matters beyond the warnings
- Python: a missing UTF-8 locale used to cause
UnicodeEncodeErrorwhen printing non-ASCII text. Python 3.7+ coerces to UTF-8 in most cases, but older tools still trip. - PostgreSQL: the database cluster’s collation comes from the locale at
initdbtime. It affects sort order and indexes. Choose it deliberately, and keep it consistent across replicas. - Sorting in scripts:
sortandlsorder differs betweenCanden_US.UTF-8. UseLC_ALL=C sortin scripts for predictable, fast results. See sort and uniq. - Number formats: in some locales the decimal separator is a comma, which can break scripts that parse numbers.
Don’t set LC_ALL permanently
LC_ALL overrides everything and is meant for one-off commands:
LC_ALL=C grep -a pattern binaryish.log
Setting it in /etc/environment or .bashrc hides other problems and can produce these very warnings if the locale is missing.
Quick reference
| Task | Command |
|---|---|
| Show current | locale |
| List available | locale -a |
| Generate (Debian/Ubuntu) | sudo locale-gen en_US.UTF-8 |
| Set default | sudo localectl set-locale LANG=en_US.UTF-8 |
| RHEL language pack | sudo dnf install glibc-langpack-en |
| Minimal UTF-8 | LANG=C.UTF-8 |
| Stop SSH forwarding | comment AcceptEnv LANG LC_* in sshd_config |
Related: hostname, time zone and environment variables.