Dialyzer "the pattern can never match the type" but error isn't the correct typespec

I’m calling a 3rd party function foo() . I can see in the library source in deps/ that the function has a type signature of :: error() | {:ok}, of which error() is {:error, Nostrum.Error.ApiError.t() | HTTPoison.Error.t()}.

Why does this code fail Dialyzer?

case foo() do
  {:error, %Nostrum.Error.ApiError{}} -> do_stuff()
  _ -> do_other_stuff()
end

Error:

The pattern can never match the type.

Pattern:
  {:error, %Nostrum.Error.ApiError{}}


Type:
  {:ok}
  | {:error, %HTTPoison.Error{<SNIP>}}

For some reason it seems like Dialyzer is not picking up the same typespec that is defined on the function since the one it’s saying it can’t match against is missing the error type I’m checking.

Raw library source of the foo() function I’m calling: nostrum/api.ex at 433641a1f4514cf5db1da01f88ee7d04b5e771ce · Kraigie/nostrum · GitHub

Not sure it’s related, but this PR just landed on nostrum:

1 Like

Yeah I am thinking of just switching to the master version instead of the pinned version at v4.6, but I’m kind of just wondering why Dialyzer is matching against a type that doesn’t match the typespec on the function regardless.

Dialyzer often ignores (just validates) the spec programmer or library author provided, and uses the “success typing” it computed on its own instead

That must be what’s going on, however if it’s just the computed success type, that’s just wrong. I ran the code and it triggers the error case I have in there. So I’m not sure how it could ignore the typespec of the function but also be wrong about the computed type :thinking:

The computed success type can be wrong e.g. when dialyzer didn’t ignore some other specs that are wrong :man_shrugging: There could be other reasons as well, like conditional compilation or meta programming usage