Why does this function cause an infinite loop when atoms are unique?

defmodule Lab do
  def convert_key_strings_to_existing_atoms(keys, raw_data) do
    try do
      keys
      |> String.to_existing_atom()
      |> IO.inspect(label: "line 1")
    rescue
      glitch ->
        glitch
        |> IO.inspect(label: "line 7")

        keys
        |> Enum.map(&String.to_atom/1)
        |> IO.inspect(label: "line 8")

        keys
        |> Enum.map(&String.to_existing_atom/1)
        |> IO.inspect(label: "line 9")

        IO.puts("\n \n")

        convert_key_strings_to_existing_atoms()
    end
  end

  def convert_key_strings_to_existing_atoms() do
    raw_data = %{
      "items" => [
        %{
          "allowed_amount" => %{"max" => 10, "min" => 0.001},
          "fees" => %{"flat" => 0.001, "rate" => 0},
          "id" => "Countach",
          "status" => "inactive"
        },
        %{
          "allowed_amount" => %{"max" => 10000, "min" => 0.001},
          "fees" => %{"flat" => 0.5, "rate" => 0},
          "id" => "Revuelto",
          "status" => "active"
        }
      ],
      "page_info" => %{"has_next_page" => false, "last_cursor" => nil},
      "type" => "list"
    }

    keys = Map.keys(raw_data)
    convert_key_strings_to_existing_atoms(keys, raw_data) 
  end
end

Results:

Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Lab.convert_key_strings_to_existing_atoms
line 7: %ArgumentError{
  message: "errors were found at the given arguments:\n\n  * 1st argument: not a binary\n"
}
line 8: [:items, :page_info, :type]
line 9: [:items, :page_info, :type]

 

line 7: %ArgumentError{
  message: "errors were found at the given arguments:\n\n  * 1st argument: not a binary\n"
}
line 8: [:items, :page_info, :type]
line 9: [:items, :page_info, :type]

 

line 7: %ArgumentError{
  message: "errors were found at the given arguments:\n\n  * 1st argument: not a binary\n"
}
line 8: [:items, :page_info, :type]
line 9: [:items, :page_info, :type]

 

line 7: %ArgumentError{
  message: "errors were found at the given arguments:\n\n  * 1st argument: not a binary\n"
}
line 8: [:items, :page_info, :type]
line 9: [:items, :page_info, :type]

Why does the try clause in convert_key_strings_to_existing_atoms/0 consistently fail, leading to an infinite loop, given that atoms can only be generated once?

You are passing a list of strings to String.to_existing_atom, not a string.

2 Likes