Search code examples
elixirhttprequestphoenix-frameworkelixir-mixhttpoison

HTTPoison ArgumentError on Phoenix mix task


I have mix task mix fetch.btc on phoenix app (lib/mix/tasks/fetch.btc.ex):

defmodule Mix.Tasks.Fetch.Btc do
  use Mix.Task

  def run(_args) do
    res = HTTPoison.get!("https://blockchain.info/ticker")
    IO.inspect(res)
  end
end

When I run mix fetch.btc I got error:

** (ArgumentError) argument error
    (stdlib) :ets.lookup_element(:hackney_config, :mod_metrics, 2)
    PROJ_DIR/deps/hackney/src/hackney_metrics.erl:27: :hackney_metrics.get_engine/0
    PROJ_DIR/deps/hackney/src/hackney_connect.erl:78: :hackney_connect.create_connection/5
    PROJ_DIR/deps/hackney/src/hackney_connect.erl:47: :hackney_connect.connect/5
    PROJ_DIR/deps/hackney/src/hackney.erl:330: :hackney.request/5
    lib/httpoison/base.ex:787: HTTPoison.Base.request/6
    lib/httpoison.ex:128: HTTPoison.request!/5
    lib/mix/tasks/fetch.btc.ex:14: Mix.Tasks.Fetch.Btc.run/1
    (mix) lib/mix/task.ex:331: Mix.Task.run_task/3
    (mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
    (elixir) lib/code.ex:767: Code.require_file/2

But in my controller this code res = HTTPoison.get!("https://blockchain.info/ticker") is work success!

Info:

hackney: 1.15.1
httpoison: 1.5.0
phoenix: 1.4.3
  1. What am I doing wrong?
  2. What is right way make http request in mix task?

Solution

  • The code in you controller runs when the application and all it’s dependencies are already started. mix tasks are run within :mix application which obviously does not start :hackney by default.

    All you need is to ensure it’s started / start it manually:

    def run(_args) do
      # ⇓⇓⇓⇓⇓⇓⇓ THIS ⇓⇓⇓⇓⇓⇓⇓
      Application.ensure_all_started(:hackney)
      # ⇑⇑⇑⇑⇑⇑⇑ THIS ⇑⇑⇑⇑⇑⇑⇑
    
      res = HTTPoison.get!("https://blockchain.info/ticker")
      IO.inspect(res)
    end