"The Inspect protocol has already been consolidated" for Ecto schema with redacted field

I’ve recently started a new Phoenix project using Elixir 1.11, Phoenix 1.5 and Ecto 3.5.

Everything runs smoothly but there is a recurrent warning in ElixirLS which I can not fix. The warning says:

the Inspect protocol has already been consolidated, an implementation for MyApp.User has no effect. If you want to implement protocols after compilation or during tests, check the “Consolidation” section in the Protocol module documentation

The warning is highlighted in the Ecto schema declaration:

image

The thing is: the module does not implement the Inspect protocol. I know I can disable protocol consolidation in development to make this warning disappear, but I would like to know what is causing it. It only happens in this schema and not in the resto of Ecto schemas I have implemented.

EDIT

I’ve dived into the Ecto.Schema.schema() code and found this code which I belive is causing the warning:

        if redacted_fields != [] and not List.keymember?(@derive, Inspect, 0) and
             @ecto_derive_inspect_for_redacted_fields do
          @derive {Inspect, except: @ecto_redact_fields}
        end

My schema has a field :password, :string, virtual: true, redact: true which triggers this code and derives the Inspect protocol for my schema.

So, now that I know where this comes from. Is there a way to fix this warning? Should I report it as a bug in Ecto?

5 Likes

Why are your protocols consolidated during development?

Well, I didn’t change any configuration related to this. So it seems to be the default behaviour for Elixir projects.

ElixirLS recompiles the project when saving updated files and it is the one triggering this warnings. Running mix compile manually does not show any warning.

1 Like

I also see this ElixirLS warning when I use:

@derive {Inspect, except: [:password]}
schema "users" do
  field :password, :string, virtual: true
  ...
end

The user schema generated by phx_gen_auth also produces this warning.

Elixir 1.11.1 (compiled with Erlang/OTP 23)

 @derive {Inspect, except: [:password]}
  schema "users" do
    field :email, :string
    field :password, :string, virtual: true
    field :hashed_password, :string
    field :confirmed_at, :naive_datetime

    timestamps()
  end

This seems to be a general issue with protocols not specific to Ecto. I’ve noticed it in other cases as well. Is someone able to reproduce it in mix?

I’ve opened an issue in Ecto repository with an example project that can be used to reproduce this warning.

2 Likes

This is a good question because digging into it made me find a potential workaround. (edit: it didn’t work :frowning:)

Reading through the Protocol docs, it mentions that consolidation isn’t used in development (due to code reloading), but consolidation still happens during compilation. We can turn that off by telling it to not consolidate in dev:

# mix.exs

def project do
  ...
  consolidate_protocols: Mix.env() != :dev
  ...
end

I am hoping that this will cause the warning to go away with no ill effects, since consolidation isn’t used in development anyways.

edit:

Within minutes the warning appears again. Apparently, disabling consolidation didn’t actually prevent it from consolidating.

Same here with elixir 1.11 and with bare default phx_gen_auth

Does anyone can explain what actually protocol consolidation is?

From the docs for Protocol:

In order to speed up dispatching in production environments, where all implementations are known up-front, Elixir provides a feature called protocol consolidation . Consolidation directly links protocols to their implementations in a way that invoking a function from a consolidated protocol is equivalent to invoking two remote functions.

1 Like

This appears to have been a Phoenix bug and is being fixed for the next version of phoenix: https://github.com/elixir-ecto/ecto/issues/3464#issuecomment-721915263 (also note that this only impacts dev and not prod environments)

1 Like

The bug has been resolved in Phoenix, which does not report the warning anymore. ElixirLS is not fixed yet and keeps showing the warning just like before.

This is the issue tracking that bug in the ElixirLS repository.

2 Likes

For what it’s worth, when using the bare phx.gen.auth generator, which puts the @derive {Inspect, except: [:password]} line on the user schema, I was getting the consolidation warning in ElixirLS but after upgrading to the latest version of Phoenix (and removing the .elixir_ls folder and letting it rebuild) I’m not seeing the warnings anymore.

2 Likes

Well, this is not what you’re supposed to do if you still want to use ElixirLS.
As far as I know there’s already a fix in Phoenix side in master (but not yet released).
But if you don’t want to use master and that you’re bothered by the warning (like I was) you can simply add this in your mix.exs file:

def project do
  [
      ..
    consolidate_protocols: Mix.env() != :test,
      ..
  ]
end
1 Like

ElixirLS bug is already fixed on master

3 Likes

I didn’t even know there was a bug in ElixirLS since it happen to be also fixed in Phoenix…
But it’s good to see you guys fixing stuff!
Thanks!

1 Like

Was this fixed?
Probably it was, the bug seems to have returned.

3 Likes

same here. annoying warning from the phx.gen.auth user schema, especially on recompile in iex

Same here. I have:

  schema "sip_accounts" do
    field :password, :string, redact: true
    field :phone_number, :string
    field :sip_proxy, :string
    field :username, :string, redact: true

and that is giving:

warning: the Inspect protocol has already been consolidated, an implementation for ResiSwitch.SIPAccounts.SIPAccount has no effect. If you want to implement protocols after compilation or during tests, check the "Consolidation" section in the Protocol module documentation
  lib/resi_switch/sip_accounts/sip_account.ex:7

yet, my user schema from phx.gen.auth isn’t giving a warning, which has the same kind of redact line:

  schema "users" do
    field :email, :string
    field :password, :string, virtual: true, redact: true
    field :hashed_password, :string, redact: true
    field :confirmed_at, :naive_datetime

I’m running into the same issue with a simple (demo) Ash Framework project. As soon as I added more than the basic persistence, started seeing:

warning: the Inspect protocol has already been consolidated, an implementation for Helpdesk.Support.Ticket has no effect. If you want to implement protocols after compilation or during tests, check the "Consolidation" section in the Protocol module documentation
  lib/helpdesk/support/resources/ticket.ex:1

The code is pretty simple:

defmodule Helpdesk.Support.Ticket do
  use Ash.Resource

  actions do
    defaults [:create, :read, :update, :destroy]

    create :open do
      accept [:subject]
    end
  end

  attributes do
    uuid_primary_key :id

    attribute :subject, :string do
      allow_nil? false
    end

    attribute :status, :atom do
      constraints [one_of: [:open, :closed]]
      default :open
      allow_nil? false
    end
  end
end
3 Likes