bash: warning: setlocale: LC_CTYPE: cannot change locale ([email protected]): Bad file descriptor
Describe the bug
I installed bash-completions@v2 from Homebrew and added the invocation stanza to my .bashrc. After this, I started seeing scary error messages when starting up my shell.
bash$ bash --login
bash: warning: setlocale: LC_CTYPE: cannot change locale ([email protected]): Bad file descriptor
bash: warning: setlocale: LC_CTYPE: cannot change locale ([email protected]): Bad file descriptor
bash: warning: setlocale: LC_COLLATE: cannot change locale ([email protected]): No such file or directory
bash: warning: setlocale: LC_CTYPE: cannot change locale ([email protected]): Bad file descriptor
bash: warning: setlocale: LC_CTYPE: cannot change locale ([email protected]): Bad file descriptor
bash: warning: setlocale: LC_COLLATE: cannot change locale ([email protected]): No such file or directory
Eventually I traced these errors to /opt/homebrew/Cellar/bash-completion@2/2.16.0/share/bash-completion/bash_completion which apparently manipulates these variables slightly carelessly.
To reproduce
- Set up your Mac for English language, but some location in Europe
- Observe that
LANGends up with a funky value likeen_US@rg=fizzzz.UTF-8 - Further observe that this causes these errors from
bash_completion
Expected behavior
Most ideally I guess it would be nice if Apple didn't assign a value that many tools cannot handle.
Somewhat less ideally, bash_completion should cope with these weird values.
Versions (please complete the following information)
- [X] Operating system name/distribution and version: MacOS Sequoia 15.7.1
- [X] bash version,
echo "$BASH_VERSION": 5.3.3(1)-release from Homebrew - [X] bash-completion version,
(IFS=.; echo "${BASH_COMPLETION_VERSINFO[*]}"): 2.16.0
Additional context
I worked around this by adding normalization of LANG and LC_CTYPE to my .bashrc before the invocation of bash_completion.
# Work around apparent MacOS bug
case $LC_CTYPE in UTF-8) LC_CTYPE=en_US.UTF-8;; esac
case $LANG in
"" | en_FI.UTF-8)
LANG=en_US.UTF-8;;
*@rg=*zzzz.*)
LANG=${LANG/@rg=*zzzz./.};;
esac
Debug trace
I don't think a full debug trace is called for here, but here is a selected snippet from the output of bash --login -x:
+++ . /opt/homebrew/etc/profile.d/bash_completion.sh
++++ '[' 'x5.3.3(1)-release' '!=' x -a $'x\\h:\\W${AWS_PROFILE+ {$AWS_PROFILE\\}}$(\n git symbolic-ref --short HEAD 2>/dev/null | sed \'/./s/.*/ [&]/\')\\$ ' '!=' x -a x = x ']'
++++ '[' 5 -gt 4 ']'
++++ '[' -r /Users/me/.config/bash_completion ']'
++++ shopt -q progcomp
++++ '[' -r /opt/homebrew/Cellar/bash-completion@2/2.16.0/share/bash-completion/bash_completion ']'
++++ . /opt/homebrew/Cellar/bash-completion@2/2.16.0/share/bash-completion/bash_completion
+++++ BASH_COMPLETION_VERSINFO=(2 16 0)
...
+++++ set +o noglob
+++++ shopt -s nullglob
+++++ shopt -u failglob dotglob
+++++ local GLOBIGNORE= GLOBSORT=name
+++++ local LC_COLLATE=C LC_CTYPE=en_US@rg=fizzzz.UTF-8 LC_ALL=
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US@rg=fizzzz.UTF-8): Bad file descriptor
I don't have macOS (and other maintainers do not seem to have macOS either), so we cannot directly check the behavior in macOS. I'm not sure if I understand the situation correctly, but do you mean LANG='en_US@rg=fizzzz.UTF-8' is a valid setup in macOS, but LC_CTYPE='en_US@rg=fizzzz.UTF-8' is not?
- Who sets the value
LANG='en_US@rg=fizzzz.UTF-8'? At leastbash-completiondoesn't set such a value. Does the macOS system set such a value? Or do you set the value in your configuration? - Without the adjustment of
LANGandLC_CTYPE, what are the results of the following commands?$ declare -p LANG "${!LC_@}" $ locale - If
@rg=fizzzzis a locale modifier, it actually should come after.UTF-8. Does the situation change if you setLANG='en_US.UTF-8@rg=fizzzz'in your~/.bashrc?
The following Stack Exchange question seems to discuss a similar issue with GNU Emacs.
This is a fresh laptop I'm setting up, I too saw the Stack Exchange question and it was good to see that it confirmed my experience. I think the conclusion is that this LANG value is what you end up with when you set up an English locale for a mainland European location.
I don't particularly care about keeping the @rg= stuff, I have found no explanation for it and it doesn't seem to do anything useful. I have a workaround in place already so I'm mainly reporting this in the hope that it can help future visitors with the same problem.
I'm not sure I even can return to a pristine state where only the OS-configured value is set, because I have tried various things already to set it straight before coming up with this workaround.
In a Terminal window which I abandoned while setting up the system because it didn't have a correct PATH or etc yet (and which thus is presumably pretty close to a pristine MacOS + Homebrew + Bash out of the box) the output of the commands you asked for is
$ declare -p LANG "${!LC_@}"
declare -- LANG="en_US.UTF-8"
$ locale
LANG=""
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
If I comment out the workaround in my .bashrc and try to move the @rg=fizzzz after the rest I get
$ LANG=en_US.UTF-8@rg=fizzzz bash --login
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8@rg=fizzzz): Bad file descriptor
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8@rg=fizzzz): Bad file descriptor
which is fewer warnings (only the LC_CTYPE ones) but not a fix.
I think, though (partially based on the output from bash --login -x etc) that LANG gets reset somewhere along the way during login and shell initialization, and that it is still somehow based on the value of defaults read -g AppleLocale (which is now en_US@rg=fizzzz, and I don't think I have changed that in any way) during the early startup of Bash.
I used UTM to set up a completely pristine MacOS Sequoia 15.6.1 virtual machine (so slightly older OS version out of the box) which I configured for English but keyboard etc and time zone set up for Finland; it comes with zsh as its default shell but I can switch to the old Apple-supplied Bash v3 with exec bash -login. Results broadly as above; except Bash says LANG is completely unset and the LC_CTYPE is a puzzling UTF-8 (which I guess I also had on my main system way back, looking at my workaround above, though that part of my configuration is several years old. I used to run that after the Bash completions stuff from Homebrew so that's why it wasn't visible before).
$ echo "$LANG"
$ defaults read -g AppleLocale
en_US@rg=fizzzz
$ declare -p LANG "$(!LC_@}"
bash: declare: LANG: not found
declare -s LC_CTYPE="UTF-8"
$ locale
LANG=""
LC_COLLATE="C"
LOC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
$ echo "$BASH_VERSION"
3.2.57(1)-release
(Well I think UTF-8 is puzzling, though perhaps it is defined somewhere that it can contain something else than the other variables. A quick search for reference documentation draws a blank but https://www.ibm.com/docs/en/aix/7.1.0?topic=locales-understanding-locale-environment-variables has an example where LC_CTYPE is en_US which is more in line with what I would have expected.)
Thank you for checking the behavior.
$ declare -p LANG "${!LC_@}" declare -- LANG="en_US.UTF-8" $ locale LANG="" LC_COLLATE="C" LC_CTYPE="C" LC_MESSAGES="C" LC_MONETARY="C" LC_NUMERIC="C" LC_TIME="C" LC_ALL=
Hmm, your LANG doesn't seem to be exported. What are the results (error messages and outputs) of the following commands?
$ export LANG='en_US@rg=fizzzz.UTF-8'
$ locale
$ export LC_CTYPE='en_US@rg=fizzzz.UTF-8'
$ locale
If I comment out the workaround in my
.bashrcand try to move the @rg=fizzzz after the rest I get$ LANG=en_US.UTF-8@rg=fizzzz bash --login bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8@rg=fizzzz): Bad file descriptor bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8@rg=fizzzz): Bad file descriptorwhich is fewer warnings (only the
LC_CTYPEones) but not a fix.
OK, so this means that @rg-fizzzz isn't a typical locale modifier.
Hmm, your LANG doesn't seem to be exported. What are the results (error messages and outputs) of the following commands?
$ export LANG='en_US@rg=fizzzz.UTF-8'
$ locale
LANG="en_US@rg=fizzzz.UTF-8"
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
$ export LC_CTYPE='en_US@rg=fizzzz.UTF-8'
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US@rg=fizzzz.UTF-8): Bad file descriptor
This is in the same "relatively pristine" terminal window where I had not yet set up most things.
OK, so this means that @rg-fizzzz isn't a typical locale modifier.
Actually I'm guessing the .UTF-8 incorrectly gets tacked on after it somewhere downstream from the OS default that you see with defaults read -g AppleLocale (carelessly, since it should go before the @ suffix).
$ export LANG='en_US@rg=fizzzz.UTF-8' WSAC9JJH41J9J:eriker-dotfiles [master]$ locale LANG="en_US@rg=fizzzz.UTF-8" LC_COLLATE="C" LC_CTYPE="C" LC_MESSAGES="C" LC_MONETARY="C" LC_NUMERIC="C" LC_TIME="C" LC_ALL=
This implies that the value LANG="en_US@rg=fizzzz.UTF-8" is ignored and isn't actually used by any locale categories, which is strange.
... $ export LC_CTYPE='en_US@rg=fizzzz.UTF-8' bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US@rg=fizzzz.UTF-8): Bad file descriptor
Thanks, but what is the result of locale after this? I wanted to know the result of locale after each assignment. The result of locale reflects how the current values of LANG and LC_* are processed.
OK, so this means that @rg-fizzzz isn't a typical locale modifier.
Actually I'm guessing the
.UTF-8incorrectly gets tacked on after it somewhere downstream from the OS default that you see withdefaults read -g AppleLocale(carelessly, since it should go before the@suffix).
If that theory is correct, I guess everything works fine with LANG='en_US@rg=fizzzz' and LC_CTYPE='en_US@rg=fizzzz'. What are the results of the following commands?
$ export LANG='en_US@rg=fizzzz'
$ locale
$ export LC_CTYPE='en_US@rg=fizzzz'
$ locale
Please also provide the results of locale after each assignment.
$ export LC_CTYPE='en_US@rg=fizzzz.UTF-8' bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US@rg=fizzzz.UTF-8): Bad file descriptorThanks, but what is the result of locale after this?
Sorry about that. It didn't change.
$ locale
LANG="en_US@rg=fizzzz.UTF-8"
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
What are the results of the following commands?
$ export LANG='en_US@rg=fizzzz' $ locale
The output is
LANG="en_US@rg=fizzzz"
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
$ export LC_CTYPE='en_US@rg=fizzzz'
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US@rg=fizzzz): Bad file descriptor
$ locale
LANG="en_US@rg=fizzzz"
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
The "Bad file descriptor" error sounds to me like it is interpreting something as an instruction to try to read from an open FD, though I have no idea what would case that. I get the same error message with
export LC_CTYPE='1'
Thank you for those results. It seems strange that the locale settings are totally ignored in all cases of the output of locale.
The "Bad file descriptor" error sounds to me like it is interpreting something as an instruction to try to read from an open FD, though I have no idea what would case that.
There was actually a similar report at #1434.
Ah, OK, in the last reply, it seems that the OP of #1434 had found that it was related to the primary language and the region settings of macOS, which exactly matches your situation. I haven't noticed the update by the OP of #1434 until now:
From https://github.com/scop/bash-completion/issues/1434#issuecomment-3319750408
Update (2025-09-23):
It turns out the issue was related to the region settings. I had English (US) as the primary language with the region set to Japan. After changing the region to the United States, the problem was resolved. Switching it back to Japan reproduced the issue.
Then, I'm interested in whether the crash found in #1434 reproduces in your environment.
From https://github.com/scop/bash-completion/issues/1434#issuecomment-3314969312
@scop @yedayak Do you have macOS? If so, does this segmentation fault reproduce in your macOS?
$ (LANG= LC_COLLATE= LC_ALL= ; printf '%f\n' 1.0) Segmentation fault: 11 ( LANG= LC_COLLATE= LC_ALL=; printf '%f\n' 1.0 )
If so, could you also try the following?
From https://github.com/scop/bash-completion/issues/1434#issuecomment-3314975282
I don't have macOS so cannot reproduce the problem, but someone who can reproduce the problem may further investigate this using
gdb,lldb, orvalgrind.$ gdb bash (gdb) r -c "LANG= LC_COLLATE= LC_ALL= ; printf '%f\n' 1.0" (gdb) bt $ valgrind bash -c "LANG= LC_COLLATE= LC_ALL= ; printf '%f\n' 1.0"
I don't get the segfault so I guess the other commands you asked for are futile for me to run, though if you still want me to, just ask.
$ (LANG= LC_COLLATE= LC_ALL= ; printf '%f\n' 1.0)
bash: warning: setlocale: LC_COLLATE: cannot change locale (): No such file or directory
1.000000
Thank you. As the segfault doesn't seem to reproduce in your environment, you don't have to run gdb, lldb, or valgrind. The "Bad file descriptor" error may be related to the file descriptor for the file that contains some data of the locale en_US@rg=fizzzz, but I'm not sure actually.
I installed MacOS Sonoma in UTM and I am able to reproduce the segfault there; but as it seems to be fixed in Sequoia, I'm not sure if this is still worth pursuing. I can install gdb and valgrind in the UTM virtual machine if you still want those results.
Perhaps also note that there is a related bug right out of the box, again on a system which I installed with English as the preferred language but Finland as the geographical location. /opt/homebrew/bin/bash --login sets a PROMPT_COMMAND which emits a warning for every prompt:
bash: warning: setlocale: LC_COLLATE: cannot change locale (): No such file or directory
though I have not been able to identify which part of that function precisely causes it (it seems to actually happen after it finishes; but if I unset PROMPT_COMMAND, the problem goes away). That's just bash, without any version of bash-completion.
I installed MacOS Sonoma in UTM and I am able to reproduce the segfault there; but as it seems to be fixed in Sequoia,
OK, thank you for checking the behavior! That's good to know that the segfault has been fixed. If this has already been fixed, no need to further pursue the cause.
though I have not been able to identify which part of that function precisely causes it (it seems to actually happen after it finishes; but if I unset
PROMPT_COMMAND, the problem goes away). That's justbash, without any version ofbash-completion.
Yeah, it's not surprising that the issue appears with random settings, given that even LC_CTYPE=$LANG seems to cause an error message.
Perhaps for the record, on a fresh Sequoia virtual machine right after installing Homebrew and Bash, and running /opt/homebrew/bin/bash --login:
$ declare -p LANG "${!LC_@}"
bash: declare: LANG: not found
declare -x LC_CTYPE="UTF-8"
$ locale
LANG=""
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
Perhaps see also https://github.com/orgs/Homebrew/discussions/6309; I left a couple of comments there.