locale: Cannot set LC_ALL to default locale: No such file or directory means LANG or LC_ALL names a locale, here en_US.UTF-8, that was never generated on this system. Install the locales package and run locale-gen en_US.UTF-8, or set the variables to C.UTF-8, which is already there.

The same missing locale makes perl print perl: warning: Setting locale failed. and bash print setlocale warnings; one fix silences all of them.

The error

docker exec fix10-lc-r4 bash -c 'echo LANG=$LANG LC_ALL=$LC_ALL; locale 2>&1'
LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=en_US.UTF-8
...

Any perl program, even a one-liner, adds its own warning and falls back to "C":

docker exec fix10-lc-r4 bash -c 'perl -e ''print qq(perl ok\n)'' 2>&1'
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 = "en_US.UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
perl ok

Why it happens

The container was started with -e LANG=en_US.UTF-8 -e LC_ALL=en_US.UTF-8, a common US English setting. The ubuntu:24.04 image has only three locales, and en_US.utf8 is not one of them:

docker exec fix10-lc-r4 bash -c 'locale -a 2>&1'
...
C
C.utf8
POSIX

bash, locale and perl each reported that the locale named in the variables could not be set. These are warnings: the perl one-liner still printed perl ok. But perl said it fell back to the plain "C" locale, and the warnings came back with every command run in that container.

The fix

Generate the locale the variables name:

docker exec fix10-lc-r4 bash -c 'apt-get update > /dev/null 2>&1; apt-get install -y locales > /dev/null 2>&1; echo install-exit=$?'
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
install-exit=0

docker exec fix10-lc-r4 bash -c 'locale-gen en_US.UTF-8 2>&1'
...
Generating locales (this might take a while)...
  en_US.UTF-8... done
Generation complete.

docker exec fix10-lc-r4 bash -c 'locale -a 2>&1; perl -e ''print qq(perl ok\n)'' 2>&1; locale 2>&1 | head -3'
C
C.utf8
en_US.utf8
POSIX
perl ok
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"

Do not be put off by the spelling in the list: locale -a shows the new locale as en_US.utf8, while the variables still say en_US.UTF-8, and the two matched in the test. The warnings stopped in the same container without restarting it, because the variables had been right all along; only the locale files were missing.

Or, when you do not need US English formats, point the variables at the locale the image already has. A container started with C.UTF-8 printed no warning:

docker run -d --name fix10-lc-r5 -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 ubuntu:24.04 sleep infinity
docker exec fix10-lc-r5 bash -c 'locale 2>&1 | head -3; perl -e ''print qq(perl ok\n)'' 2>&1'
LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
perl ok

Setting LC_ALL=C.UTF-8 only for one command inside the broken container quietened perl but not the outer shell, which had already read the old value; change the variables where they are set (in this test, the docker run line), not per command.

How it was reproduced

The capture was made in ubuntu:24.04 containers (Ubuntu 24.04.5 LTS, bash 5.2.21) on Docker Engine 29.9.3, the broken one started with docker run -d --name fix10-lc-r4 -e LANG=en_US.UTF-8 -e LC_ALL=en_US.UTF-8 ubuntu:24.04 sleep infinity; it was not run in WSL. The installed package was locales 2.39-0ubuntu8.12. The fix10-lc- container names are the test's own. Every command was sent from Windows PowerShell 5.1 exactly as shown, with the -c text in single quotes so it reached the container unchanged; a single quote inside that text is written twice, as PowerShell requires.

Frequently asked

How do I fix perl: warning: Setting locale failed in Ubuntu?
Generate the locale your LANG and LC_ALL name: apt-get install -y locales, then locale-gen en_US.UTF-8. In the test perl then ran without warnings.
Why does locale say Cannot set LC_ALL to default locale?
LC_ALL names a locale that is not generated. In the test locale -a listed only C, C.utf8 and POSIX while LC_ALL was en_US.UTF-8.
Can I use C.UTF-8 instead of en_US.UTF-8?
Yes, ubuntu:24.04 already has it. A container started with LANG and LC_ALL set to C.UTF-8 printed no locale warning in the test.

More decoded errors in the Fixes category.