FWIW and to mimic what you are doing :
In one shell I have :
$ locale
LANG="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL="en_US.UTF-8"
$ _build/default/rel/my_app/bin/my_app foreground
Exec: ...
Then in another shell :
$ _build/default/rel/my_app/bin/my_app eval 'lists:keyfind(encoding, 1, io:getopts()).'
{encoding, unicode}
$ env LC_ALL="not_utf_8" _build/default/rel/my_app/bin/my_app eval 'lists:keyfind(encoding, 1, io:getopts()).'
{encoding, unicode}
So, you can see setting LC_ALL for the eval did nothing, this makes sense, as we’re evaling the expression on the running node.
Likewise, I can start up a release like so :
env LANG="not_utf_8" LC_ALL="not_utf_8" _build/default/rel/my_app/bin/my_app foreground
Exec: ...
Then back over on the other shell :
env LC_ALL="en_US.UTF-8" _build/default/rel/my_app/bin/my_app eval 'lists:keyfind(encoding, 1, io:getopts()).'
{encoding, latin1}
You can see from the above, the environment variable has no effect here, because we are evaluating what encoding got set to on the running node.
As such, I still suggest doubling back to see what’s going on with the environment your release is starting in, but I am glad you have found a temporary work-around.