OmegaNalphA

OmegaNalphA

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?

Showing Posts 1 to 5

OmegaNalphA

OmegaNalphA OP

After searching more, I found this open issue that “solves” the problem I’m facing by downgrading the protocol to http1. Mint adapter cannot upload more than 65535 bytes on HTTP/2 · Issue #394 · elixir-tesla/tesla · GitHub

That being said, still not sure why my dialyzer is not working

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.

OmegaNalphA

OmegaNalphA OP

Definitely! The code is called here:

  defp do_generate(%{messages: _messages} = params, stream, opts) do
    opts
    |> OpenAI.Client.new()
    |> OpenAI.Chat.create_completion(params, opts)
    |> handle_response(stream: stream)
  end

In the create_completion function

  def create_completion(client, params, opts \\ []) do
    client
    |> Client.post("/v1/chat/completions", params, opts)
    |> Client.handle_response(opts)
  end

The client handle_response

  @doc false
  @spec handle_response(result(), Keyword.t()) :: {:ok, body()} | {:error, term()}
  def handle_response(response, opts \\ [])

  def handle_response({:ok, %Tesla.Env{status: status, body: body}}, _opts) when status >= 400,
    do: {:error, body}

  def handle_response({:ok, %Tesla.Env{body: body}}, _opts), do: {:ok, body}

  def handle_response({:error, _reason} = err, _opts), do: err

I’m realizing doing this it might be from the handle_response of the client, maybe I need to update that one?

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
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.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews