elixir
elixir copied to clipboard
`IEx.Helpers.c/1` no longer writes compilation errors to attached remote console
Elixir and Erlang/OTP versions
Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]
Elixir 1.16.2 (compiled with Erlang/OTP 24)
Operating system
Debian 12
Current behavior
On Elixir 1.16.2, starting a brand new Mix project, then:
$ echo "IO.puts(a)" > script.exs
$ iex --sname main -S mix
iex(main@iris)1> c("script.exs")
error: undefined variable "a"
│
1 │ IO.puts(a)
│ ^
│
└─ script.exs:1:9
== Compilation error in file script.exs ==
** (CompileError) script.exs: cannot compile file (errors have been logged)
** (CompileError) compile error
(iex 1.16.2) lib/iex/helpers.ex:210: IEx.Helpers.c/2
But if doing the same thing from a remote shell:
$ iex --sname baz --remsh main
Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.16.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(main@iris)1> c("script.exs")
** (CompileError) compile error
(iex 1.16.2) lib/iex/helpers.ex:210: IEx.Helpers.c/2
iex(main@iris)1>
while the actual compilation error is shown on the "main" shell:
iex(main@iris)1> error: undefined variable "a"
│
1 │ IO.puts(a)
│ ^
│
└─ script.exs:1:9
== Compilation error in file script.exs ==
** (CompileError) script.exs: cannot compile file (errors have been logged)
Expected behavior
On Elixir 1.13, the compilation error is shown on the remote shell:
$ iex --sname baz --remsh main
sh: 1: exec: tty_sl: not found
Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.13.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(main@iris)1> c("script.exs")
== Compilation error in file script.exs ==
** (CompileError) script.exs:1: undefined function a/0 (there is no such import)
(elixir 1.13.0) lib/kernel/parallel_compiler.ex:347: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/7
** (CompileError) compile error
(iex 1.13.0) lib/iex/helpers.ex:203: IEx.Helpers.c/2
iex(main@iris)1>
This is extremely useful when running ad-hoc scripts on running systems. On Elixir 1.16, the compilation error is still logged on stderr
of the main Elixir process, which can be accessed with journalctl
when running an Elixir release with systemd for example, but it's not as intuitive as having the full error logged in the shell that requested the compilation.
I suspect this was broken by the new parallel compiler introduced in 1.15.
Thank you!
This is tricky. Compilation warnings/errors print to stderr which I would believe to be the semantically correct place (while before it did not). However, Erlang does not redirect stderr
across nodes, which means they stay in the original shell.
We have three options:
- Change Erlang to also redirect stderr across nodes
- Change the compiler to print to stdout
- Make the compiler detect if it is running a remote node and send to stdout only in such cases
I am not happy with any of them.
Agreed, the solutions all seem "hacky", except maybe for the first one but that's a bigger change. I think it's good to have this issue documented though, because from a developer's perspective, it's a workflow that has been broken.
For now, I will just use journalctl
to check stderr
of the Elixir release process, that works even if a bit tedious.
Thanks for looking into it!
Can you send a PR to document that any compilation error is written to stderr and therefore, in case of remote nodes, it will be available in the parent node? Thank you.