Fixing the SSH `LC_CTYPE=UTF-8` locale warning on Debian/LMDE
When SSH-ing from macOS into a fresh Debian/LMDE box, bash greets you with a repeated warning:
bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
Harmless, but noisy. Here’s what’s going on and how to fix it server-side.
Why it happens
macOS Terminal (and iTerm) forward locale env vars to the remote host by default, sending values like LC_CTYPE=UTF-8 or LC_ALL=UTF-8. That literal string UTF-8 is not a valid locale name — proper names look like en_US.UTF-8.
The server’s sshd accepts these via AcceptEnv LANG LC_* (default in Debian’s /etc/ssh/sshd_config). When bash starts and calls setlocale() with UTF-8, glibc cannot find a locale by that name and prints the warning. The shell keeps running with the fallback locale, so nothing actually breaks — but the warning fires once per setlocale() call during startup, hence the repetition.
Quick reproduction on the server itself:
$ env -i LC_ALL=UTF-8 bash -c 'echo hi'
bash: warning: setlocale: LC_ALL: cannot change locale (UTF-8): No such file or directory
hi
The fix (server side)
Tell glibc that UTF-8 is a valid locale name by generating it as an alias for en_US UTF-8:
sudo apt install -y locales locales-all
sudo localedef -i en_US -f UTF-8 UTF-8
sudo update-locale LANG=en_US.UTF-8
What each step does:
locales— provideslocale-gen/localedefand the locale definition sources.locales-all— pre-generates every locale glibc knows about, saves reconfigure round trips.localedef -i en_US -f UTF-8 UTF-8— the actual fix: builds a locale literally namedUTF-8from theen_USinput file withUTF-8charmap. This is the entrysetlocale("UTF-8")was failing to find.update-locale LANG=en_US.UTF-8— ensures the system default is sane and written to/etc/default/locale.
Verifying
Confirm the new locale is registered:
$ locale -a | grep -i utf-8
UTF-8
en_US.utf8
...
Then reproduce the earlier failing command:
$ env -i LC_ALL=UTF-8 bash -c 'echo ok'
ok
No warning. Open a fresh SSH session from macOS — clean login banner.
Alternatives (not used here)
- Client side: stop macOS Terminal from forwarding locale env vars (Terminal → Preferences → Profiles → Advanced → uncheck Set locale environment variables on startup), or add
SendEnv -LC_*to~/.ssh/config. Only fixes it for that one client. - Server side, blunter: comment out
AcceptEnv LANG LC_*in/etc/ssh/sshd_configand reload sshd. Server then ignores whatever the client sends.
The localedef approach is the least invasive: fixes the actual root cause (missing locale definition), works for every client, no config file surgery.
Environment
- Server: LMDE 7 (gigi), glibc 2.41.
- Client: macOS Terminal (default profile forwards
LC_*).