I assume its a beam issue i have. I don’t know honestly.
Setup
my project contains fallowing module:
defmodule MyApp.Access do
def permissions() do
%{
permission_x: [:list, :show],
...
}
end
end
In total project has 7 places where this atom permission_x is hardcoded.
Steps to consistently reproduce issue.
open new terminal tab.
~ mix phx.server → server starts
in browser i request 127.0.0.1:4000 → i get error. This error seems odd, as i have module where required atom is hardcoded, so how can it be not an already existing atom, but ok?
[error] #PID<0.766.0> running MayAppWeb.Endpoint (connection #PID<0.765.0>, stream id 1) terminated
Server: 127.0.0.1:4000 (http)
Request: GET /
** (exit) an exception was raised:
** (ArgumentError) errors were found at the given arguments:
* 1st argument: not an already existing atom
:erlang.binary_to_existing_atom("permission_x", :utf8)
I make arbitrary change to MyApp.Access module: (can’t add empty line, as on-save it is removed by formatter, so just added :ok)
defmodule MyApp.Access do
+ :ok
def permissions() do
in browser i request 127.0.0.1:4000 → and it works → terminal output:
Compiling 4 files (.ex)
[info] GET /
[info] Sent 200 in 262ms
I can remove :ok line and it keeps working. → I assume compilation part is the secret sauce that fixes issue.
If i stop server ctrl+c and start again (step 2). im back in step 3. it does not work again. and i need to do some arbitrary changes to MyApp.Access to force compilation.
Is there a way to see what files are compiled there? Maybe there is some secret.
Also why it after restart loads old/stale binary of MyApp.Access not the latest one that worked?
I have spent a lot time to debug this and i dont understand what could even be next steps to try to fix this.
I assume compilation part is the secret sauce that fixes issue.
Yeah, compilation loads this module, therefore the atom is loaded.
Perhaps, you can try to ensure that the module is loaded, or just run any function from this module, because erlang loads modules on demand
The beam can start in one of two modes (configured through build_embedded iirc). Either it preloads all modules at the start, or it does load modules only on demand, when e.g. some code tries to call a function on it. By default in dev the beam runs in the second mode for the improved speed in startup. I’d expect that to be the reason for what you’re seeing
I even created another module and tried to convert string to atom that was defined in an other module and it worked. I asume sample mix project start with first embeded mode, but phoenix (which is more complex framework configures it differently)