Phoenix: Code reloading in umbrella app

Created on 31 Oct 2016  ·  10Comments  ·  Source: phoenixframework/phoenix

Environment

  • Elixir version (elixir -v): Elixir 1.3.4 & Elixir 1.4.0-dev
  • Phoenix version (mix deps): 1.2.1
  • NodeJS version (node -v): v7.0.0
  • NPM version (npm -v): 3.10.8
  • Operating system: macOS Sierra

Expected behavior

Code recompiles without issue

Actual behavior

While running my Phoenix app in dev in iex, very often, but seemingly randomly, it will raise:

** (RuntimeError) trying to access Mix.Project.app_path for an umbrella project but umbrellas have no app
    (mix) lib/mix/lib/mix/project.ex:415: Mix.Project.app_path/1
    (mix) lib/mix/lib/mix/project.ex:519: Mix.Project.ensure_structure/2
    (mix) lib/mix/lib/mix/compilers/elixir.ex:138: Mix.Compilers.Elixir.compile_manifest/7
    (mix) lib/mix/lib/mix/compilers/elixir.ex:78: Mix.Compilers.Elixir.compile/5
    (mix) lib/mix/task.ex:294: Mix.Task.run_task/3
    (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
    (phoenix) lib/phoenix/code_reloader/server.ex:135: Phoenix.CodeReloader.Server.mix_compile/1
    (phoenix) lib/phoenix/code_reloader/server.ex:103: Phoenix.CodeReloader.Server.mix_compile/3
    (phoenix) lib/phoenix/code_reloader/server.ex:41: anonymous fn/2 in Phoenix.CodeReloader.Server.handle_call/3
    (phoenix) lib/phoenix/code_reloader/server.ex:155: Phoenix.CodeReloader.Server.proxy_io/1
    (phoenix) lib/phoenix/code_reloader/server.ex:39: Phoenix.CodeReloader.Server.handle_call/3
    (stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
    (stdlib) gen_server.erl:647: :gen_server.handle_msg/5
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Seems like my app isn't being seen as an umbrella app somewhere along the line? AFAIK my project is set up as a totally standard umbrella app.

I've tried to dig around a bit, but I haven't gotten very far. FWIW, when the error is raised the value of Mix.Project.config() in Mix.Compilers.Elixir.compile_manifest/7 is:

[app: nil, aliases: [], build_per_environment: true, build_scm: Mix.SCM.Path,
 config_path: "config/config.exs", consolidate_protocols: true,
 default_task: "run", deps_path: "deps", elixirc_paths: ["lib"],
 erlc_paths: ["src"], erlc_include_path: "include", erlc_options: [:debug_info],
 lockfile: "mix.lock", preferred_cli_env: [], apps_path: "apps",
 build_embedded: false, start_permanent: false, deps: []]

Possibly related: #463

Most helpful comment

Btw, thank you very much for the mechanism to reproduce this, it made my life much easier!

All 10 comments

I could not reproduce it in a new umbrella. Can you push to Github a simple application that reproduces the error? thank you!

Ok, I'll try to get something reproducible. I found I can pretty reliably trigger it on a certain page of my app.

I have a similar problem, although I get several different errors in addition to the one @nlap is seeing. I think it's an issue when you have two phoenix apps under one umbrella, with one app depending on the other. Here's an app that reproduces: https://github.com/crevalle/phoenix_reload_test

Environment

  • Elixir 1.3.4
  • Phoenix 1.2.1
  • macos sierra

Steps to Reproduce

  • From umbrella root, run $ iex -S mix phoenix.server
  • Edit the file apps/a/web/templates/page/index.html.eex by adding any text or html.

Expected Behavior

App A hot-reloads the page and the changed text appears.

Actual Behavior

App A crashes with the following stack trace:

==> b
Error while loading project :a at /Users/desmond/code/phoenix_reload_test
** (Mix.Error) Trying to load A.Mixfile from "/Users/desmond/code/phoenix_reload_test/apps/a/mix.exs" but another project with the same name was already defined at "/Users/desmond/code/phoenix_reload_test/apps/a/mix.exs"
    (mix) lib/mix.ex:274: Mix.raise/1
    (mix) lib/mix/project.ex:462: Mix.Project.load_project/2
    (mix) lib/mix/project.ex:203: Mix.Project.in_project/4
    (elixir) lib/file.ex:1145: File.cd!/2
    (mix) lib/mix/dep.ex:176: Mix.Dep.in_dependency/3
    (mix) lib/mix/dep/loader.ex:55: Mix.Dep.Loader.load/2
    (mix) lib/mix/dep/umbrella.ex:31: anonymous fn/2 in Mix.Dep.Umbrella.loaded/0
    (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
    (mix) lib/mix/dep/umbrella.ex:30: Mix.Dep.Umbrella.loaded/0
    (phoenix) lib/phoenix/code_reloader/server.ex:97: Phoenix.CodeReloader.Server.mix_compile/3
    (phoenix) lib/phoenix/code_reloader/server.ex:41: anonymous fn/2 in Phoenix.CodeReloader.Server.handle_call/3
    (phoenix) lib/phoenix/code_reloader/server.ex:152: Phoenix.CodeReloader.Server.proxy_io/1
    (phoenix) lib/phoenix/code_reloader/server.ex:39: Phoenix.CodeReloader.Server.handle_call/3
    (stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
    (stdlib) gen_server.erl:647: :gen_server.handle_msg/5
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Compiling 7 files (.ex)
warning: redefining module A.PageController (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.PageController.beam)
  web/controllers/page_controller.ex:1

warning: redefining module A.Endpoint (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.Endpoint.beam)
  lib/a/endpoint.ex:1

warning: redefining module A.Router (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.Router.beam)
  web/router.ex:1

warning: redefining module A (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.beam)
  lib/a.ex:1

warning: redefining module A.ErrorView (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.ErrorView.beam)
  web/views/error_view.ex:1

[error] Ranch protocol #PID<0.508.0> (:cowboy_protocol) of listener B.Endpoint.HTTP terminated
** (exit) killed
Compiling 7 files (.ex)
warning: redefining module A.LayoutView (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.LayoutView.beam)
  web/views/layout_view.ex:1

warning: redefining module A.Router (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.Router.beam)
  web/router.ex:1

warning: redefining module A.Endpoint (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.Endpoint.beam)
  lib/a/endpoint.ex:1

warning: redefining module A.PageController (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.PageController.beam)
  web/controllers/page_controller.ex:1

warning: redefining module A (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.beam)
  lib/a.ex:1

[error] #PID<0.538.0> running B.Endpoint terminated
Server: localhost:4001 (http)
Request: GET /
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function B.Endpoint.call/2 is undefined (module B.Endpoint is not available)
        (b) B.Endpoint.call(%Plug.Conn{...})

== Compilation error on file web/router.ex ==
** (CompileError) web/router.ex:1: cannot define module A.Router because it is currently being defined in web/router.ex:1
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1

warning: redefining module A.Router.Helpers (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.Router.Helpers.beam)
  web/router.ex:1

warning: redefining module A.PageView (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/a/ebin/Elixir.A.PageView.beam)
  web/views/page_view.ex:1

==> a
Compiling 6 files (.ex)
warning: redefining module A.Endpoint (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.Endpoint.beam)
  lib/a/endpoint.ex:1

warning: redefining module A.PageController (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.PageController.beam)
  web/controllers/page_controller.ex:1

warning: redefining module A.ErrorView (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.ErrorView.beam)
  web/views/error_view.ex:1

warning: redefining module A.Router (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.Router.beam)
  web/router.ex:1

warning: redefining module A.LayoutView (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.LayoutView.beam)
  web/views/layout_view.ex:1

warning: redefining module A.PageView (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.PageView.beam)
  web/views/page_view.ex:1

warning: redefining module A.Router.Helpers (current version loaded from /Users/desmond/code/phoenix_reload_test/_build/dev/lib/b/ebin/Elixir.A.Router.Helpers.beam)
  web/router.ex:1

Doing various permutations of removing _build and cleaning deps will cause other similar errors. I've also seen the following, in case this helps:

(File.Error) could not set current working directory to "apps/a": no such file or directory
    (elixir) lib/file.ex:1127: File.cd!/1
    (elixir) lib/file.ex:1143: File.cd!/2
    (mix) lib/mix/task.ex:387: anonymous fn/4 in Mix.Task.recur/1
    (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
    (mix) lib/mix/task.ex:386: Mix.Task.recur/1
    (mix) lib/mix/project_stack.ex:135: Mix.ProjectStack.recur/1
    (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
    (phoenix) lib/phoenix/code_reloader/server.ex:132: Phoenix.CodeReloader.Server.mix_compile/1
    (phoenix) lib/phoenix/code_reloader/server.ex:103: Phoenix.CodeReloader.Server.mix_compile/3
    (phoenix) lib/phoenix/code_reloader/server.ex:41: anonymous fn/2 in Phoenix.CodeReloader.Server.handle_call/3
    (phoenix) lib/phoenix/code_reloader/server.ex:152: Phoenix.CodeReloader.Server.proxy_io/1
    (phoenix) lib/phoenix/code_reloader/server.ex:39: Phoenix.CodeReloader.Server.handle_call/3
    (stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
    (stdlib) gen_server.erl:647: :gen_server.handle_msg/5
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Editing a file in app B will cause a similar failure.

This has been fixed in Elixir master. ❤️

Btw, thank you very much for the mechanism to reproduce this, it made my life much easier!

@josevalim I'm still seeing the issue with Elixir 1.4.0-dev (ee09043) :(.

The error is nondeterministic, but I usually get a variant of

[debug] Live reload: apps/b/web/templates/page/index.html.eex
[debug] Live reload: apps/b/web/templates/page/index.html.eex
==> b
Error while loading project :b at /Users/desmond/code/phoenix_reload_test/apps/b
** (Mix.Error) Trying to load B.Mixfile from "/Users/desmond/code/phoenix_reload_test/apps/b/mix.exs" but another project with the same name was already defined at "/Users/desmond/code/phoenix_reload_test/apps/b/mix.exs"
    (mix) lib/mix.ex:274: Mix.raise/1
    (mix) lib/mix/project.ex:462: Mix.Project.load_project/2
    (mix) lib/mix/project.ex:203: Mix.Project.in_project/4
    (elixir) lib/file.ex:1145: File.cd!/2
    (mix) lib/mix/dep.ex:176: Mix.Dep.in_dependency/3
    (mix) lib/mix/dep/loader.ex:55: Mix.Dep.Loader.load/2
    (mix) lib/mix/dep/umbrella.ex:31: anonymous fn/2 in Mix.Dep.Umbrella.loaded/0
    (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
    (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
    (mix) lib/mix/dep/umbrella.ex:30: Mix.Dep.Umbrella.loaded/0
    (mix) lib/mix/task.ex:386: Mix.Task.recur/1
    (mix) lib/mix/task.ex:372: Mix.Task.reenable/1
    (elixir) lib/enum.ex:651: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:651: Enum.each/2
    (phoenix) lib/phoenix/code_reloader/server.ex:127: Phoenix.CodeReloader.Server.mix_compile/1
    (phoenix) lib/phoenix/code_reloader/server.ex:103: Phoenix.CodeReloader.Server.mix_compile/3
    (phoenix) lib/phoenix/code_reloader/server.ex:41: anonymous fn/2 in Phoenix.CodeReloader.Server.handle_call/3
    (phoenix) lib/phoenix/code_reloader/server.ex:152: Phoenix.CodeReloader.Server.proxy_io/1
    (phoenix) lib/phoenix/code_reloader/server.ex:39: Phoenix.CodeReloader.Server.handle_call/3
    (stdlib) gen_server.erl:615: :gen_server.try_handle_call/4

Compiling 1 file (.ex)
Compiling 1 file (.ex)

== Compilation error on file web/views/page_view.ex ==
** (CompileError) /Users/desmond/code/phoenix_reload_test/apps/b/web/views/page_view.ex:1: cannot define module B.PageView because it is currently being defined in web/views/page_view.ex:1
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1

I can refresh the pages manually, but then code reloading stops working altogether - changing a file does not trigger a page refresh, and the changes don't show up even when I manually refresh the page. The logs show the server processing the request, but no changes appear.

@desmondmonster oh, could it be because you have two tabs open, each pointing to a different app, and then both are attempting to reload at the same time? Can you please confirm this?

@desmondmonster if that is the case, it should be fixed in Phoenix master: 32b84e260df08f71642c526e4b8b1b7ec6959fa0

Yes- I did have both apps open in two tabs simultaneously. I'm away from my computer now but will check out Phoenix master later today. Thanks for the prompt response!

Sent from my wireless.

On Nov 5, 2016, at 1:37 PM, José Valim [email protected] wrote:

@desmondmonster if that is the case, it should be fixed in Phoenix master: 32b84e2


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@josevalim using that ref on Phoenix master fixed my problem. It's really convenient having both apps open at the same time in different tabs.

thank you!

Was this page helpful?
0 / 5 - 0 ratings