How to solve the dialyzer error about HTTPoison.post

I have a piece of code as shown below.

    url = ~c"#{a}/ccc/xyz/#{b}?access_token=#{c}"
    # success
    post_payload =
      Jason.encode!(%{
        s: "#{d}",
        c: "t",
        e: 1
      })

    headers = [{"Content-type", "application/json"}]

    case HTTPoison.post(url, post_payload, headers, []) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        ....

      {:error, %HTTPoison.Error{reason: _reason}} ->
        ....

      _ ->
        ....
    end

and when I ran mix dialyzer,it reponsed with the error message:

The function call will not succeed.

HTTPoison.post(
  _url :: string(),
  _post_payload :: binary(),
  _headers :: [{<<_::96>>, <<_::128>>}, ...],
  []
)

will never return since the success typing is:
(binary(), any(), any(), Keyword.t()) ::
  {:error, %HTTPoison.Error{:__exception__ => true, :id => nil, :reason => _}}
  | {:ok,
     %{
       :__struct__ =>
         HTTPoison.AsyncResponse | HTTPoison.MaybeRedirect | HTTPoison.Response,
       :body => _,
       :headers => [any()],
       :id => reference(),
       :redirect_url => _,
       :request => %HTTPoison.Request{
         :body => _,
         :headers => _,
         :method => :delete | :get | :head | :options | :patch | :post | :put,
         :options => _,
         :params => _,
         :url => binary()
       },
       :request_url => _,
       :status_code => integer()
     }}

and the contract is
(binary(), any(), headers(), Keyword.t()) ::
  {:ok, HTTPoison.Response.t() | HTTPoison.AsyncResponse.t() | HTTPoison.MaybeRedirect.t()}
  | {:error, HTTPoison.Error.t()}

I had spent several hours checking my code, but I found nothing wrong.
I don’t know what went wrong with my code.

Thanks.

Why you are using Erlang’s charlist here?

You should change it to:

`    url = "#{a}/ccc/xyz/#{b}?access_token=#{c}"`

or rewrite your case to for example:

    url
    |> List.to_string()
    |> HTTPoison.post(post_payload, headers, [])
    |> then(fn
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        ....

      {:error, %HTTPoison.Error{reason: _reason}} ->
        ....

      _ ->
        ....
    end)

Note: I have changed case to then as it’s preferred in pipelines.

2 Likes

Thanks.

It’s actually because I use Erlang’s charlist.
You saved my life.