(ArgumentError) argument error (stdlib) :ets.lookup_element(:hackney_config, :mod_metrics, 2)

(Please note: Elixir Experience Level: Beginner)


** (ArgumentError) argument error
    (stdlib) :ets.lookup_element(:hackney_config, :mod_metrics, 2)
    /home/maxximiliann/arbit/deps/hackney/src/hackney_metrics.erl:27: :hackney_metrics.get_engine/0
    /home/maxximiliann/arbit/deps/hackney/src/hackney_connect.erl:78: :hackney_connect.create_connection/5
    /home/maxximiliann/arbit/deps/hackney/src/hackney_connect.erl:47: :hackney_connect.connect/5
    /home/maxximiliann/arbit/deps/hackney/src/hackney.erl:333: :hackney.request/5
    lib/httpoison/base.ex:793: HTTPoison.Base.request/6
    lib/pump.ex:11: Pump.get_trading_activity/0

How do I resolve this error?

Thanks for all your help :slight_smile:

There should be error indicating issue ets encoutered. I have had my fair share of issues with ets and the community is great with noobs to help them out. you can check out my issue to know what stracktrace I am referring to and also might help you in debugging

As far as I remember ets will give an argument error when the table does not exist.

This again could happen if the owning application isn’t started yet.

Could you perhaps show us your code? At least the function around line 11 in pump.ex, as that’s the initial caller in the stack trace.

Also, how do you run your program to get this error?

Erlang/Elixir libraries are packaged as applications, with start and stop functions responsible for initializing or tearing down everything the app needs to run: supervision tree, registered processes, ETS tables, etc.

In this case the missing resource is an ETS table which Hackney creates when it starts:

Most likely you can fix it by ensuring Hackney is started. In mix.exs, how did you specify the dependency? Make sure it doesn’t have a flag like runtime: false or only: :test.

If you’re on an old Elixir, you may also have to add it under applications, which controls what applications (dependencies) get started before your app. More modern Elixir uses extra_applications instead and generally figure out dependencies automatically.

If you didn’t specify Hackney as a dependency at all - then perhaps it got brought in indirectly by HTTPoison. Then you need to make sure that HTTPoison is being started instead, which should automatically start Hackney.

There’s some more discussion on that in the tutorial: https://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html#the-application-callback

1 Like

Here’s the code:

def get_trading_activity do

 		case HTTPoison.get("https://api.wavesplatform.com/v0/pairs") do
			{:ok, _} ->
			results = HTTPoison.get!("https://api.wavesplatform.com/v0/pairs")

			%{data: items} = Poison.decode!(results.body, keys: :atoms)
			
			market_snapshot = Enum.map(items, fn item ->
  				%{
    					asset: item.amountAsset,
    					priced_in: item.priceAsset,
    					last: get_in(item, [:data, :lastPrice]),					
    					volume: get_in(item, [:data, :volumeWaves])
  				}
				    end)

			#IO.inspect(market_snapshot, limit: :infinity)

		#Exclude all pairs with volumeWAVES < 500

			volume_greater_than_500 = Enum.filter(market_snapshot, fn map -> map.volume >= 500 end)
			
			#IO.inspect(volume_greater_than_500, limit: :infinity) 
			
			total_pairs = Enum.count(volume_greater_than_500, &(&1.asset))  
			
			opportunities = [total_pairs: total_pairs] ++ volume_greater_than_500			
					
			{:error, %Elixir.HTTPoison.Error{reason: reason}} ->
 			
			IO.inspect reason

		end

Here’s how the error came up:

$ iex -S mix compile
Erlang/OTP 21 [erts-10.2.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Compiling 1 file (.ex)
warning: variable "opportunities" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/pump.ex:36

warning: unused alias Asset_Pairs
  lib/pump.ex:3

warning: unused alias Repo
  lib/pump.ex:3

Interactive Elixir (1.8.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Pump.get_trading_activity
** (ArgumentError) argument error
    (stdlib) :ets.lookup_element(:hackney_config, :mod_metrics, 2)
    /home/maxximiliann/arbit/deps/hackney/src/hackney_metrics.erl:27: :hackney_metrics.get_engine/0
    /home/maxximiliann/arbit/deps/hackney/src/hackney_connect.erl:78: :hackney_connect.create_connection/5
    /home/maxximiliann/arbit/deps/hackney/src/hackney_connect.erl:47: :hackney_connect.connect/5
    /home/maxximiliann/arbit/deps/hackney/src/hackney.erl:333: :hackney.request/5
    lib/httpoison/base.ex:793: HTTPoison.Base.request/6
    lib/pump.ex:11: Pump.get_trading_activity/0

From mix.exs:

defmodule Arbit.MixProject do
  use Mix.Project

  def project do
    [
      app: :arbit,
      version: "0.1.0",
      elixir: "~> 1.8",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end


  def application do
    [
      extra_applications: [:logger]
    ]
  end


  defp deps do
    [
    	{:httpoison, "~> 1.6"},
	{:poison, "~> 4.0"},
	{:postgrex, "~> 0.15.1"},
	{:ecto_sql, "~> 3.2.0"}
    ]
  end
end

Is this correct?

It looks fine. Try iex -S mix (or iex -S mix run) rather than iex -S mix compile.

mix run loads and runs your application and its dependencies, whereas mix compile only compiles the application without starting it. You’ll see the difference if you call Application.started_applications() in your iex shell after starting it.

3 Likes

Perfect! That did it. Thanks so much!! :slight_smile: :slight_smile: :slight_smile:

I encountered the same error when running integration changes on prod when initializing the meilisearch-elixir module. What was really odd was I wasn’t encountering this error stack on a separate project using the same module. So I’m assuming it was a race condition here:

faithful_word    | ** (ArgumentError) errors were found at the given arguments:
faithful_word    | 
faithful_word    |   * 1st argument: the table identifier does not refer to an existing ETS table
faithful_word    | 
faithful_word    |     (stdlib 3.15.2) :ets.lookup_element(:hackney_config, :mod_metrics, 2)
faithful_word    |     /app/deps/hackney/src/hackney_metrics.erl:27: :hackney_metrics.get_engine/0
faithful_word    |     /app/deps/hackney/src/hackney_connect.erl:75: :hackney_connect.create_connection/5
faithful_word    |     /app/deps/hackney/src/hackney_connect.erl:44: :hackney_connect.connect/5
faithful_word    |     /app/deps/hackney/src/hackney.erl:335: :hackney.request/5
faithful_word    |     lib/httpoison/base.ex:846: HTTPoison.Base.request/6
faithful_word    |     lib/meilisearch/http.ex:40: Meilisearch.HTTP.delete_request/3
faithful_word    |     (stdlib 3.15.2) erl_eval.erl:685: :erl_eval.do_apply/6

The solution was quite similar, I had to ensure that :httpoison and :poison were started before launching:

defmodule FaithfulWord.ReleaseTasks do
  @start_apps [
    :crypto,
    :ssl,
    :postgrex,
    :ecto,
    :ecto_sql,
    :httpoison, # add
    :poison # add
  ]

... 
  defp start_services do
    IO.puts("Starting dependencies..")
    # Start apps necessary for executing migrations
    Enum.each(@start_apps, &Application.ensure_all_started/1)

    # Start the Repo(s) for app
    IO.puts("Starting repos..")
    Enum.each(@repos, & &1.start_link(pool_size: 2))
  end
1 Like

That shouldn’t be necessary since Elixir can infer the required start order by default. Are you setting :applications in mix.exs? Or are you setting runtime: false on those deps?

Not setting :applications in mix.exs nor setting runtime: false on those deps. Should I be setting :applications?

this is my config in mix.exs:

  def project do
    [
      app: :faithful_word,
      version: "0.1.0",
      elixir: "~> 1.12",
      elixirc_paths: elixirc_paths(Mix.env()),
      compilers: [:phoenix, :gettext] ++ Mix.compilers(),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps(),
      releases: releases()
    ]
  end
  defp releases do
    [
      faithful_word: [
        version: "0.1.0",
        applications: [
          faithful_word: :permanent
        ]
      ]
    ]
  end

EDIT:

  def application do
    [
      mod: {FaithfulWord.Application, []},
      extra_applications: [:logger, :runtime_tools, :iex]
    ]
  end

No, using :extra_applications like what you are using is what I would recommend.

Ah, I see what’s happening. Normally I’d let Application.ensure_all_started(:faithful_word) start all of the dependencies of your application. But since you’re starting all the dependencies manually you have to add any transitive dependencies (i.e. dependencies of your dependencies) as well.

2 Likes

Good to know, thanks!