OmegaNalphA

OmegaNalphA

Dialyzer error - trying to handle :error responses with multiple values in the error tuple

I’m having an issue getting my Dialyzer to agree with my output, and can’t seem to figure it out. Essentially, the response is {:error, %Mint.HTTP2{}, %Mint.HTTPError{}} instead of just {:error, _} and I can’t get the spec to reflect that.

This is the issue I’m facing, I keep getting an error from my Mint transport service (which is a whole separate issue) but I keep getting alerts that my handle_response isn’t able to match the type. After looking into it more the error tuple has two arguments in the shape of: {:error, %Mint.HTTP2{}, %Mint.HTTPError{}}.

Here is my handle_response:

  @spec handle_response(
          {:ok, [map()] | function()}
          | {:error, String.t()}
          | {:error, %Mint.HTTP2{}, %Mint.HTTPError{}},
          Keyword.t()
        ) ::
          {:ok, [map()] | function()} | {:error, term()}
  defp handle_response(resp, opts)

  defp handle_response({:ok, stream} = resp, stream: true) when is_function(stream), do: resp

  defp handle_response({:ok, resp}, opts) when is_binary(resp),
    do: handle_response({:ok, Jason.decode!(resp)}, opts)

  defp handle_response({:ok, resp}, _), do: {:ok, Map.get(resp, "choices", [])}

  defp handle_response({:error, _} = err, _), do: err

  defp handle_response({:error, http, http_error}, _)
       when is_map(http) and is_map(http_error),
       do: {:error, http_error}

But I keep getting an error from my dialyzer here:

lib/broadcast.ex:129:pattern_match
The pattern can never match the type.

Pattern:
{:error, _http, _http_error}, _

Type:
{:error, _} | {:ok, _}, [{:stream, _}, ...]

I’m not sure why, I’m pretty sure the spec should be correct. Can anyone see what would be incorrect about this or does this seem reasonable?

Marked As Solved

al2o3cr

al2o3cr

(assuming that do_generate and the handle_response from your initial post are in the same module)

Dialyzer is telling you the {:error, _, _} branch in handle_response can’t be reached because create_completion’s return type matches Client.handle_response ({:ok, body()} | {:error, term()})

As shown, Client.handle_response will crash if Client.post returns {:error, _, _}, since it doesn’t have a matching clause. You’ll likely need to update:

  • the definition of result in Client, if it doesn’t include the 3-tuple case already
  • the return type for Client.handle_response, if you want to handle the 3-tuple case in the caller instead of in Client

Also Liked

LostKobrakai

LostKobrakai

One thing to understand with dialyzer is that it starts out not caring about your spec at all.

Dialyzer does type inference. And for the given functions it inferred that the input will never be a tuple-3. Your function matches on such a tuple though, which is surfaced as an error.

The spec of the function is compared against inferred values and mismatches (as in the spec doesn’t have overlap with the inferred value) are reported. Iirc the overlap between the inferred type and the spec for the return type is then used as the input to later inferrence.

So an incorrect typespec can mess up validation on deeped down in the callstack function calls, but typespec cannot “widen” what would be considered a possible input to a function call compared to the inferred value.

al2o3cr

al2o3cr

Can you show the code that calls handle_response? The error message suggests that Dialyzer has inferred that the {:error, map(), map()} case “can’t happen” despite it being observed in production.

Where Next?

Popular in Questions Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
gonzofish
I’m currently trying to understand how to join three tables using Ecto. All the examples I’ve seen use 2, so maybe I’m just missing somet...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement