Using the default generated controller, I'm getting the following warning. I also received the warning when tinkering with adding another route. Clearly I'm doing something incorrectly, but it is not obvious from the error message.
warning: HelloWeb.HelloWeb.PageController.init/1 is undefined (module HelloWeb.HelloWeb.PageController is not available or is yet to be defined)
lib/hello_web/router.ex:26: HelloWeb.Router.__checks__/0
My search results indicate there is generally a mismatch between the controller module name being used in the router, vs the one actually defined, but if that is the case I am unable to detect the difference.
defmodule HelloWeb.Router do
alias HelloWeb.PageController
use HelloWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {HelloWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :fetch_current_user
end
scope "/", HelloWeb do
pipe_through :browser
# I should note that this line produces the following warning in VSCode using the Phoenix extension
# "HelloWeb.HelloWeb.PageController.init/1 is undefined (module HelloWeb.HelloWeb.PageController is not available or is yet to be defined)"
get "/", PageController, :home
end
defmodule HelloWeb.PageController do
use HelloWeb, :controller
def home(conn, _params) do
# The home page is often custom made,
# so skip the default app layout.
render(conn, :home, layout: false)
end
end
What stands out to me here is that the warning refers to HelloWeb.HelloWeb.PageController
though the module is named HelloWeb.PageController
. I don't know the cause of the discrepancy, or even if it is related to the actual issue.
init/1
function?EDIT: Based on the helpful solution below, I discovered that the VSCode ElixirLS extension inserts aliases by default if required, which then breaks the way Phoenix handles routing. This can be disabled in the extension settings:
The downside is that disabling this seems to break autocomplete.
It has to do with the scoping of the router. When you do scope "/", HelloWeb
, your router knows to look for controllers under the HelloWeb.
prefix. So, you don't need to alias your controllers. By adding the alias, your router is duplicating the HelloWeb
part of the module's name, as you can see on the warning.
So:
init/1
is the function that gets called when spawning new processes, so your router is probably trying to spawn a module at HelloWeb.HelloWeb.PageController
, but since that module doesn't exist with the double HelloWeb
, it fails to find it and call its init/1
function.