Module Phoenix.Component is not loaded and could not be found

I went from Phoenix 1.5 to 1.7 and I’m still facing an error when compiling the project.

elixir 1.17.3-otp-27
erlang 27.1

Here is the compilation error:


    error: module Phoenix.Controller is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
    │
  2 │   use AppNameWeb, :html
    │   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    │
    └─ lib/app_name_web/controllers/error_html.ex:2: AppNameWeb.ErrorHTML (module)

    error: module Gettext is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
    │
 21 │   use Gettext, backend: AppNameWeb.Gettext
    │   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    │
    └─ lib/app_name_web/components/core_components.ex:21: AppNameWeb.CoreComponents (module)

    error: module Phoenix.Controller is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
    │
  2 │   use AppNameWeb, :controller
    │   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    │
    └─ lib/app_name_web/controllers/page_controller.ex:2: AppNameWeb.PageController (module)

    error: module Phoenix.Controller is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
    │
  2 │   use AppNameWeb, :html
    │   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    │
    └─ lib/app_name_web/components/layouts.ex:2: AppNameWeb.Layouts (module)


== Compilation error in file lib/app_name_web/components/core_components.ex ==
** (CompileError) lib/app_name_web/components/core_components.ex: cannot compile module AppNameWeb.CoreComponents (errors have been logged)
    (elixir 1.17.3) expanding macro: Kernel.use/2
    lib/app_name_web/components/core_components.ex:21: AppNameWeb.CoreComponents (module)

It can also be:

error: module Phoenix.Component is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
│
17 │   use Phoenix.Component
│   ^^^^^^^^^^^^^^^^^^^^^
│
└─ lib/app_name_web/components/core_components.ex:17: AppNameWeb.CoreComponents (module)

error: module Phoenix.Controller is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
│
2 │   use AppNameWeb, :controller
│   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
│
└─ lib/app_name_web/controllers/page_controller.ex:2: AppNameWeb.PageController (module)

error: module Phoenix.Component is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
│
2 │   use AppNameWeb, :html
│   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
│
└─ lib/app_name_web/components/layouts.ex:2: AppNameWeb.Layouts (module)

error: module Phoenix.Component is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
│
2 │   use AppNameWeb, :html
│   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
│
└─ lib/app_name_web/controllers/error_html.ex:2: AppNameWeb.ErrorHTML (module)


== Compilation error in file lib/app_name_web/components/core_components.ex ==
** (CompileError) lib/app_name_web/components/core_components.ex: cannot compile module AppNameWeb.CoreComponents (errors have been logged)
(elixir 1.17.3) expanding macro: Kernel.use/1
lib/app_name_web/components/core_components.ex:17: AppNameWeb.CoreComponents (module)

The mix.exs before:

defmodule AppName.MixProject do
  use Mix.Project

  def project do
    [
      app: :app_name,
      version: "0.1.5",
      elixir: "~> 1.9",
      elixirc_paths: elixirc_paths(Mix.env()),
      compilers: [:phoenix, :gettext] ++ Mix.compilers(),
      build_embedded: Mix.env == :prod,
      start_permanent: Mix.env == :prod,
      aliases: aliases(),
      deps: deps(),
      releases: [
        app_name: [
          include_executables_for: [:unix],
          applications: [runtime_tools: :permanent]
        ]
      ]
    ]
  end

  # Configuration for the OTP application.
  #
  # Type `mix help compile.app` for more information.
  def application do
    [
      mod: {AppName.Application, []},
      extra_applications: [:logger, :runtime_tools, :google_maps, :edeliver]
    ]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [
      {:ecto_sql, "~> 3.4"},
      {:gettext, "~> 0.11"},
      {:google_maps, "~> 0.11"},
      {:distillery, "~> 2.1.1"},
      {:edeliver, "~> 1.8.0"},
      {:jason, "~> 1.0"},
      {:phoenix, "~> 1.5.7"},
      {:phoenix_ecto, "~> 4.1"},
      {:phoenix_html, "~> 2.11"},
      {:phoenix_live_dashboard, "~> 0.4"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:platformshconfig, "~> 0.1.0"},
      {:plug_cowboy, "~> 2.0"},
      {:telemetry_metrics, "~> 0.4"},
      {:telemetry_poller, "~> 0.4"}
    ]
  end

  # Aliases are shortcuts or tasks specific to the current project.
  # For example, to install project dependencies and perform other setup tasks, run:
  #
  #     $ mix setup
  #
  # See the documentation for `Mix` for more info on aliases.
  defp aliases do
    [
      setup: ["deps.get", "cmd npm install --prefix assets"]
    ]
  end
end

The mix.exs now:

defmodule AppName.MixProject do
  use Mix.Project

  def project do
    [
      app: :app_name,
      version: "0.1.6",
      elixir: "~> 1.9",
      elixirc_paths: elixirc_paths(Mix.env()),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps(),
      releases: [
        app_name: [
          include_executables_for: [:unix],
          applications: [runtime_tools: :permanent]
        ]
      ]
    ]
  end

  # Configuration for the OTP application.
  #
  # Type `mix help compile.app` for more information.
  def application do
    [
      applications: [
        :edeliver
      ],
      mod: {AppName.Application, []},
      extra_applications: [:logger, :runtime_tools, :google_maps, :edeliver]
    ]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [
      {:dart_sass, "~> 0.7", runtime: Mix.env() == :dev},
      {:distillery, "~> 2.1"},
      {:edeliver, ">= 1.9.2"},
      {:esbuild, "~> 0.7", runtime: Mix.env() == :dev},
      {:expo, "~> 0.5"},
      {:gettext, "~> 0.25.0"},
      {:google_maps, "~> 0.11"},
      {:jason, "~> 1.0"},
      {:phoenix, "~> 1.7"},
      {:phoenix_html, "~> 3.0"},
      {:phoenix_live_view, ">=  0.20.0"},
      {:phoenix_live_dashboard, "~> 0.8.2"},
      {:phoenix_live_reload, "~> 1.2"},
      {:platformshconfig, "~> 0.1.0"},
      {:plug_cowboy, "~> 2.5"},
      {:telemetry_metrics, "~> 0.6"},
      {:telemetry_poller, "~> 0.5"}
    ]
  end

  # Aliases are shortcuts or tasks specific to the current project.
  # For example, to install project dependencies and perform other setup tasks, run:
  #
  #     $ mix setup
  #
  # See the documentation for `Mix` for more info on aliases.
  defp aliases do
    [
      "assets.deploy": [
        "sass default --no-source-map --style=compressed",
        "esbuild default --minify",
        "phx.digest"],
      setup: ["deps.get"]
    ]
  end
end

The file lib/app_name_web.ex looks like that:

defmodule AppNameWeb do
  @moduledoc """
  The entrypoint for defining your web interface, such
  as controllers, views, channels and so on.

  This can be used in your application as:

      use AppNameWeb, :controller
      use AppNameWeb, :view

  The definitions below will be executed for every view,
  controller, etc, so keep them short and clean, focused
  on imports, uses and aliases.

  Do NOT define functions inside the quoted expressions
  below. Instead, define any helper function in modules
  and import those modules here.
  """
  def static_paths do
    ~w(assets fonts images favicon.ico robots.txt)
  end

  def router do
    quote do
      use Phoenix.Router, helpers: false

      import Plug.Conn
      import Phoenix.Controller
      import Phoenix.LiveView.Router
    end
  end

  def controller do
    quote do
        use Phoenix.Controller,
            formats: [:html, :json],
            layouts: [html: AppNameWeb.Layouts]

        import Plug.Conn
        # import AppNameWeb.Gettext
        use Gettext, backend: AppNameWeb.Gettext

        unquote(verified_routes())
    end
  end

  def html do
      quote do
          use Phoenix.Component
          # Import convenience functions from controllers

          import Phoenix.Controller,
              only: [get_csrf_token: 0, view_module: 1, view_template: 1]

          # Include general helpers for rendering HTML
          unquote(html_helpers())
      end
  end

  defp html_helpers do
      quote do
          # HTML escaping functionality
          import Phoenix.HTML

          # Core UI components and translation
          import AppNameWeb.CoreComponents
          # import AppNameWeb.Gettext
          use Gettext, backend: AppNameWeb.Gettext

          # Shortcut for generating JS commands
          alias Phoenix.LiveView.JS

          # Routes generation with the ~p sigil
          unquote(verified_routes())
      end
  end

  def verified_routes do
      quote do
          use Phoenix.VerifiedRoutes,
              endpoint: AppNameWeb.Endpoint,
              router: AppNameWeb.Router,
              statics: AppNameWeb.static_paths()
      end
  end

  @doc """
  When used, dispatch to the appropriate controller/view/etc.
  """
  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end
end

Then, lib\app_name_web\components\core_components.ex starts with:

defmodule AppNameWeb.CoreComponents do
  @moduledoc """
  Provides core UI components.
  """
  use Phoenix.Component

  alias Phoenix.LiveView.JS
  # import AppNameWeb.Gettext
  use Gettext, backend: AppNameWeb.Gettext

And finally, lib\app_name_web\gettext.ex:

defmodule AppNameWeb.Gettext do
  @moduledoc """
  A module providing Internationalization with a gettext-based API.
  """
  use Gettext.Backend, otp_app: :app_name
  # use Gettext, otp_app: :app_name
end

I followed the tutorial here: Upgrading to Phoenix 1.7.
And (when I had a doubt) I checked on this project files:github.com/byronsalty/app_name.

It’s been few days now and I still struggle with this issue, I hope it’s a silly typo or something that can be fixed easily.

Thank you! :smiley:

My go to in situations like this is to do a clean compile.

mix do clean, compile

or even nuke the whole _build and deps folders, then do

mix do deps.get, compile

In a lot of cases this solves the error.

1 Like

Unfortunately, it’s not working.
I’ve already removed _build and deps before each compilation to be sure it was not due to that. (I retryed just now to be sure and got the same result)

The fix for me seemed to be adding the latest

{:phoenix_live_view, “~> 1.0.0”}

to mix.exs

Yeah, prior to v1.6 the Phoenix generator for new applications did not include LiveView by default – see changelog.

For folks passing through in the future, here are the Phoenix 1.5.x to 1.6 upgrade instructions that covers manually adding LiveView to the dependencies.