`iex` crashes with recent erlang installs

iex errors when trying to output the result of an expression I type in for recent installs of erlang (errors with 26.1 and 26.1 but not 26.0.2).

$ asdf shell erlang 26.0.2
$ iex
Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)
iex> 2 + 2

$ asdf shell erlang 26.1
$ iex
Erlang/OTP 26 [erts-14.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)
iex> 2 + 2
Failed to write log message to stdout, trying stderr

09:26:39.936 [error] GenServer #PID<0.64.0> terminating
** (FunctionClauseError) no function clause matching in :prim_tty.cols/2
    (kernel 9.1) prim_tty.erl:980: :prim_tty.cols([{:ansi, "\e[G"}, "\e[35m", 105, 101, 120, 62, "\e[0m", 32, 50, 32, 43, 32, 50], true)
    (kernel 9.1) prim_tty.erl:978: :prim_tty."-cols_multiline/4-lc$^0/1-0-"/3
    (kernel 9.1) prim_tty.erl:978: :prim_tty.cols_multiline/4
    (kernel 9.1) prim_tty.erl:915: :prim_tty.in_view/1
    (kernel 9.1) prim_tty.erl:597: :prim_tty.handle_request/2
    (kernel 9.1) prim_tty.erl:590: :prim_tty.handle_request/2
    (kernel 9.1) user_drv.erl:779: :user_drv.io_request/2
    (kernel 9.1) user_drv.erl:828: :user_drv.io_requests/2
Last message: {:EXIT, #PID<0.69.0>, {:function_clause, [{:prim_tty, :cols, [[{:ansi, "\e[G"}, "\e[35m", 105, 101, 120, 62, "\e[0m", 32, 50, 32, 43, 32, 50], true], [file: ~c"prim_tty.erl", line: 980]}, {:prim_tty, :"-cols_multiline/4-lc$^0/1-0-", 3, [file: ~c"prim_tty.erl", line: 978]}, {:prim_tty, :cols_multiline, 4, [file: ~c"prim_tty.erl", line: 978]}, {:prim_tty, :in_view, 1, [file: ~c"prim_tty.erl", line: 915]}, {:prim_tty, :handle_request, 2, [file: ~c"prim_tty.erl", line: 597]}, {:prim_tty, :handle_request, 2, [file: ~c"prim_tty.erl", line: 590]}, {:user_drv, :io_request, 2, [file: ~c"user_drv.erl", line: 779]}, {:user_drv, :io_requests, 2, [file: ~c"user_drv.erl", line: 828]}]}}
State: {:state, :user_sup, :undefined, #PID<0.69.0>, {#PID<0.64.0>, :user_sup}}

I just installed erlang 26.1.2, same effect.

I tried googling the function clause error but didn’t find an exact match.

Everything else seems to function normally.

Any help and hints much appreciated.

I cannot reproduce it locally. Do you have a custom prompt or any IEx configuration?

1 Like

Sometimes I feel very dumb. Turns out I do have a custom .iex.exs, I just didn’t recall creating it.

  colors: [
    enabled: true
  default_prompt: [
      "\e[G",     # ANSI CHA, move cursor to column 1
      "\e[35m",   # ANSI magenta
      "%prefix",  # IEx prompt variable
      ">",        # plain string
      "\e[0m"     # ANSI reset
    ] |> IO.chardata_to_string

I have no idea where that comes from. Removing it resolves the issue (of course).

Thank you

1 Like

This is definitely a bug though, we would need to isolate and report it upstream. My guess is that Erlang doesn’t like ANSI in prompts.

1 Like

I have a similar customized terminal prompt and recently hit this same error (on ubuntu 20.04) after upgrading to OTP-26.

After eliminating the first line that moves the cursor to column 1 and converting the other values to atoms resolved the error for me:

    colors: [
      syntax_colors: [
        number: :light_yellow,
        atom: :light_cyan,
        string: :light_black,
        boolean: [:light_blue],
        nil: [:magenta, :bright]
      ls_directory: :cyan,
      ls_device: :yellow,
      doc_code: :green,
      doc_inline_code: :magenta,
      doc_headings: [:cyan, :underline],
      doc_title: [:cyan, :bright, :underline]
        "🧪 iex",
      |> IO.ANSI.format()
      |> IO.chardata_to_string()

I tried this, but without the “move cursor to column 1” when you hit up or down arrows to scroll through history, it seems to continuously build the prompt. (ie: keeps adding additional :test_tube: to start of prompt)

Yes. I previously had that line in my .iex.exs file but it broke functionality after upgrading to OTP 26. By this I mean that hitting up and trying to rerun previous commands failed.

Removing the line, IEX is usable, but the UI issue with duplicating :test_tube:s in the prompt happens. I’m not sure why the "\e[G" (move cursor to column 1) line broke on OTP 26, and still need to look into it further.