Dialyzer: no local return : Ecto.Repo.get_by/3

Tags: #<Tag:0x00007f11421f9be0> #<Tag:0x00007f11421f9aa0> #<Tag:0x00007f11421f9960>


Dialyzer complains about this below:

lib/my_app/accounts/accounts.ex:134: Function authenticate_by_username_password/2 has no local return

def authenticate_by_username_password(username, given_password) do
  user = User
    |> Repo.get_by(username: username)
    |> Repo.preload(:credential)

  cond do
    user && checkpw(given_password, user.credential.password_hash) ->
      {:ok, user}
    user ->
      {:error, :unauthorized}
    true ->
      {:error, :not_found}

As mentioned in the doc If the struct in the queryable has no or more than one primary key, it will raise an argument error.

Moreover, the return value of get_by/3 could be :

Ecto.Schema.t() |
nil |

Does that mean that if an argument error is raised by get_by/3, then the cond block won’t be executed, moreover authenticate_by_username_password/2 return value will be set to type no_return(), which finally makes dialyzer complain like that?

If so, should I try to catch the possible argument error of get_by/3? Or just let it go :wink:.



I’m terrible at Dialyzer but…

  1. Yes, any exception anywhere that isn’t rescued will result in a non-local return. But thats ok if you have described none() or no_return() in the @spec for your function.

  2. Do you have a @spec for the function? Since Dialyzer is a “success typing” tool it helps if it knows your intention.

  3. Are you also getting Dialyzer warnings on checkpw and dummy_checkpw?

  1. I have added the spec below but I am still getting the warning.
    @spec authenticate_by_username_password(String.t(), String.t()) :: {:ok, Ecto.Schema.t()} | {:error, atom()} | no_return()

  2. I have just added it.

  3. No warning on checkpw and dummy_checkpw.


Are there no dialyzer errors in related code at all?

The fact that the Ecto function can raise in some cases shouldn’t matter, when Dialyzer says “no local return” it means none at all. Here I would suspect something is wrong with checkpw.