phoenixframework / phoenix

Peace of mind from prototype to production
https://www.phoenixframework.org
MIT License
21.41k stars 2.87k forks source link

function Phoenix.HTML.FormData.to_form/2 is undefined in dev mode #4951

Closed agreif closed 1 year ago

agreif commented 2 years ago

Environment

Expected behavior

after installing a new phoenix app with the 'phx.gen.auth' addition in dev mode: every GET request to 'http://localhost:4000/users/log_in' should respind with the login form

Actual behavior

in dev mode: repeated call to the 'http://localhost:4000/users/log_in' URl via GET throws sometimes but quite often the following error:

[error] #PID<0.693.0> running DemoWeb.Endpoint (connection #PID<0.541.0>, stream id 51) terminated
Server: localhost:4000 (http)
Request: GET /users/log_in
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function Phoenix.HTML.FormData.to_form/2 is undefined or private
        (phoenix_html 3.2.0) Phoenix.HTML.FormData.to_form(%Plug.Conn{adapter: {Plug.Cowboy.Conn, :...}, assigns: %{current_user: nil, error_message: nil, layout: {DemoWeb.LayoutView, "app.html"}}, body_params: %{}, cookies: %{"_demo_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYdE83MWxQTVVBUDlKMVVrU1J0VWpFSnpR.Ny9UdEDEgmZM5jhRIruZZLJMnwKwpi4z38oqxVAZ23U", "_hive_rec_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYQi1OQzJWR3ZobjVYR0toNzl5c293aFlO.ixPFMAmsLTBuIMDfjQtqITqG2vRxPe8t5mQPMfKqrLc"}, halted: false, host: "localhost", method: "GET", owner: #PID<0.693.0>, params: %{}, path_info: ["users", "log_in"], path_params: %{}, port: 4000, private: %{DemoWeb.Router => {[], %{Plug.Swoosh.MailboxPreview => ["mailbox"]}}, :before_send => [#Function<0.16477574/1 in Plug.CSRFProtection.call/2>, #Function<2.17183421/1 in Phoenix.Controller.fetch_flash/2>, #Function<0.77458138/1 in Plug.Session.before_send/2>, #Function<0.23023616/1 in Plug.Telemetry.call/2>, #Function<1.120844262/1 in Phoenix.LiveReloader.before_send_inject_reloader/3>], :phoenix_action => :new, :phoenix_controller => DemoWeb.UserSessionController, :phoenix_endpoint => DemoWeb.Endpoint, :phoenix_flash => %{}, :phoenix_format => "html", :phoenix_layout => {DemoWeb.LayoutView, :app}, :phoenix_request_logger => {"request_logger", "request_logger"}, :phoenix_root_layout => {DemoWeb.LayoutView, :root}, :phoenix_router => DemoWeb.Router, :phoenix_template => "new.html", :phoenix_view => DemoWeb.UserSessionView, :plug_session => %{"_csrf_token" => "tO71lPMUAP9J1UkSRtUjEJzQ"}, :plug_session_fetch => :done}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %{"_demo_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYdE83MWxQTVVBUDlKMVVrU1J0VWpFSnpR.Ny9UdEDEgmZM5jhRIruZZLJMnwKwpi4z38oqxVAZ23U", "_hive_rec_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYQi1OQzJWR3ZobjVYR0toNzl5c293aFlO.ixPFMAmsLTBuIMDfjQtqITqG2vRxPe8t5mQPMfKqrLc"}, req_headers: [{"accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"}, {"accept-encoding", "gzip, deflate"}, {"accept-language", "en-US,en;q=0.5"}, {"connection", "keep-alive"}, {"cookie", "_hive_rec_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYQi1OQzJWR3ZobjVYR0toNzl5c293aFlO.ixPFMAmsLTBuIMDfjQtqITqG2vRxPe8t5mQPMfKqrLc; _demo_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYdE83MWxQTVVBUDlKMVVrU1J0VWpFSnpR.Ny9UdEDEgmZM5jhRIruZZLJMnwKwpi4z38oqxVAZ23U"}, {"host", "localhost:4000"}, {"referer", "http://localhost:4000/users/log_in"}, {"upgrade-insecure-requests", "1"}, {"user-agent", "Mozilla/5.0 (X11; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0"}], request_path: "/users/log_in", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "FxVj9rZvaHcpykMAAANx"}, {"x-frame-options", "SAMEORIGIN"}, {"x-xss-protection", "1; mode=block"}, {"x-content-type-options", "nosniff"}, {"x-download-options", "noopen"}, {"x-permitted-cross-domain-policies", "none"}, {"cross-origin-window-policy", "deny"}], scheme: :http, script_name: [], secret_key_base: :..., state: :unset, status: nil}, [as: :user])
        (phoenix_live_view 0.17.11) lib/phoenix_live_view/helpers.ex:1107: Phoenix.LiveView.Helpers.form/1
        (phoenix_live_view 0.17.11) lib/phoenix_live_view/helpers.ex:637: Phoenix.LiveView.Helpers.component/2
        (demo 0.1.0) lib/demo_web/templates/user_session/new.html.heex:3: anonymous fn/2 in DemoWeb.UserSessionView."new.html"/1
        (phoenix_live_view 0.17.11) lib/phoenix_live_view/engine.ex:124: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/1
        (phoenix_live_view 0.17.11) lib/phoenix_live_view/engine.ex:140: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/3
        (phoenix 1.6.12) lib/phoenix/controller.ex:772: Phoenix.Controller.render_and_send/4
        (demo 0.1.0) lib/demo_web/controllers/user_session_controller.ex:1: DemoWeb.UserSessionController.action/2
        (demo 0.1.0) lib/demo_web/controllers/user_session_controller.ex:1: DemoWeb.UserSessionController.phoenix_controller_pipeline/2
        (phoenix 1.6.12) lib/phoenix/router.ex:354: Phoenix.Router.__call__/2
        (demo 0.1.0) lib/demo_web/endpoint.ex:1: DemoWeb.Endpoint.plug_builder_call/2
        (demo 0.1.0) lib/plug/debugger.ex:136: DemoWeb.Endpoint."call (overridable 3)"/2
        (demo 0.1.0) lib/demo_web/endpoint.ex:1: DemoWeb.Endpoint.call/2
        (phoenix 1.6.12) lib/phoenix/endpoint/cowboy2_handler.ex:54: Phoenix.Endpoint.Cowboy2Handler.init/4
        (cowboy 2.9.0) /home/agreif/project/demo/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.9.0) /home/agreif/project/demo/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
        (cowboy 2.9.0) /home/agreif/project/demo/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
        (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
[debug] Duplicate channel join for topic "phoenix:live_reload" in Phoenix.LiveReloader.Socket. Closing existing channel for new join.
josevalim commented 2 years ago

This is not possible because Phoenix.HTML itself defines this protocol. Please try deleting _build and trying again just in case?

agreif commented 2 years ago

deleted _build... called 'http://localhost:4000/users/log_in' two times which were ok, and the third call brought the exact same error. reloading worked again fine another reload brought error again. 3 times reloading worked fine then a reload threw the error again.

So in average 2-4 request are fine and the the error occures. sometimes it need 20-30 reloads in the browser an then the error happens

agreif commented 2 years ago

Here are the exact steps I did:

[agreif@nixos:~/project]$ mix phx.new auth                                                                                                                                            
* creating auth/config/config.exs                                                                                                                                                     
* creating auth/config/dev.exs                                                                                                                                                        
* creating auth/config/prod.exs                                                                                                                                                       
* creating auth/config/runtime.exs                                                                                                                                                    
* creating auth/config/test.exs                                                                                                                                                       
* creating auth/lib/auth/application.ex                                                                                                                                               
* creating auth/lib/auth.ex                                                                                                                                                           
* creating auth/lib/auth_web/views/error_helpers.ex                                                                                                                                   
* creating auth/lib/auth_web/views/error_view.ex                                                                                                                                      
* creating auth/lib/auth_web/endpoint.ex                                                                                                                                              
* creating auth/lib/auth_web/router.ex                                                                                                                                                
* creating auth/lib/auth_web/telemetry.ex                                                                                                                                             
* creating auth/lib/auth_web.ex                                                                                                                                                       
* creating auth/mix.exs                                                                                                                                                               
* creating auth/README.md                                                                                                                                                             
* creating auth/.formatter.exs                                                                                                                                                        
* creating auth/.gitignore                                                                                                                                                            
* creating auth/test/support/conn_case.ex                                                                                                                                             
* creating auth/test/test_helper.exs                                                                                                                                                  
* creating auth/test/auth_web/views/error_view_test.exs                                                                                                                               
* creating auth/lib/auth/repo.ex                                                                                                                                                      
* creating auth/priv/repo/migrations/.formatter.exs                                                                                                                                   
* creating auth/priv/repo/seeds.exs                                                                                                                                                   
* creating auth/test/support/data_case.ex                                                                                                                                             
* creating auth/lib/auth_web/controllers/page_controller.ex                                                                                                                           
* creating auth/lib/auth_web/views/page_view.ex                                                                                                                                       
* creating auth/test/auth_web/controllers/page_controller_test.exs                                                                                                                    
* creating auth/test/auth_web/views/page_view_test.exs                                                                                                                                
* creating auth/assets/vendor/topbar.js                                                                                                                                               
* creating auth/lib/auth_web/templates/layout/root.html.heex                                                                                                                          
* creating auth/lib/auth_web/templates/layout/app.html.heex                                                                                                                           
* creating auth/lib/auth_web/templates/layout/live.html.heex                                                                                                                          
* creating auth/lib/auth_web/views/layout_view.ex                                                                                                                                     
* creating auth/lib/auth_web/templates/page/index.html.heex                                                                                                                           
* creating auth/test/auth_web/views/layout_view_test.exs                                                                                                                              
* creating auth/lib/auth/mailer.ex                                                                                                                                                    
* creating auth/lib/auth_web/gettext.ex                                                                                         
* creating auth/priv/gettext/en/LC_MESSAGES/errors.po                                                                           
* creating auth/priv/gettext/errors.pot                                                                                         
* creating auth/assets/css/phoenix.css                                                                                          
* creating auth/assets/css/app.css                                                         
* creating auth/assets/js/app.js             
* creating auth/priv/static/robots.txt                                                     
* creating auth/priv/static/images/phoenix.png                                             
* creating auth/priv/static/favicon.ico                                                    

Fetch and install dependencies? [Yn]                                                       
* running mix deps.get                       
* running mix deps.compile                   

We are almost there! The following steps are missing:                                      

    $ cd auth                                

Then configure your database in config/dev.exs and run:                                    

    $ mix ecto.create                        

Start your Phoenix app with:                 

    $ mix phx.server                         

You can also run your app inside IEx (Interactive Elixir) as:                              

    $ iex -S mix phx.server                  

[agreif@nixos:~/project]$ mv auth/ phx-auth                                                
[agreif@nixos:~/project]$ cd phx-auth/                                                     

adjusted DB settings

[agreif@nixos:~/project/phx-auth]$ mix ecto.create                                         
warning: the :gettext compiler is no longer required in your mix.exs.                                                                                                                 

Please find the following line in your mix.exs and remove the :gettext entry:                                                                                                         

    compilers: [..., :gettext, ...] ++ Mix.compilers(),                                    

  (gettext 0.20.0) lib/mix/tasks/compile.gettext.ex:5: Mix.Tasks.Compile.Gettext.run/1                                                                                                
  (mix 1.13.4) lib/mix/task.ex:397: anonymous fn/3 in Mix.Task.run_task/3                                                                                                             
  (mix 1.13.4) lib/mix/tasks/compile.all.ex:92: Mix.Tasks.Compile.All.run_compiler/2                                                                                                  
  (mix 1.13.4) lib/mix/tasks/compile.all.ex:72: Mix.Tasks.Compile.All.compile/4                                                                                                       
  (mix 1.13.4) lib/mix/tasks/compile.all.ex:59: Mix.Tasks.Compile.All.with_logger_app/2                                                                                               
  (mix 1.13.4) lib/mix/tasks/compile.all.ex:36: Mix.Tasks.Compile.All.run/1                                                                                                           

Compiling 14 files (.ex)                     
Generated auth app                           
The database for Auth.Repo has already been created                                        

removed getttext in mix.exs

started server once without auth

[agreif@nixos:~/project/phx-auth]$ mix phx.server                                          
Generated auth app                           
[info] Running AuthWeb.Endpoint with cowboy 2.9.0 at 127.0.0.1:4000 (http)                                                                                                            
[info] Access AuthWeb.Endpoint at http://localhost:4000                                    
[watch] build finished, watching for changes...                                            
[info] GET /                                 
[debug] Processing with AuthWeb.PageController.index/2                                     
  Parameters: %{}                            
  Pipelines: [:browser]                      
[info] Sent 200 in 311ms                     
^C                                           
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo                             
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution                                
^C                                           

installed auth

[agreif@nixos:~/project/phx-auth]$ mix phx.gen.auth Accounts User users                                                                                                     [107/1729]

* creating priv/repo/migrations/20220922070058_create_users_auth_tables.exs                                                                                                           
* creating lib/auth/accounts/user_notifier.ex                                              
* creating lib/auth/accounts/user.ex                                                       
* creating lib/auth/accounts/user_token.ex                                                 
* creating lib/auth_web/controllers/user_auth.ex                                           
* creating test/auth_web/controllers/user_auth_test.exs                                    
* creating lib/auth_web/views/user_confirmation_view.ex                                    
* creating lib/auth_web/templates/user_confirmation/new.html.heex                                                                                                                     
* creating lib/auth_web/templates/user_confirmation/edit.html.heex                                                                                                                    
* creating lib/auth_web/controllers/user_confirmation_controller.ex                                                                                                                   
* creating test/auth_web/controllers/user_confirmation_controller_test.exs                                                                                                            
* creating lib/auth_web/templates/layout/_user_menu.html.heex                              
* creating lib/auth_web/templates/user_registration/new.html.heex                                                                                                                     
* creating lib/auth_web/controllers/user_registration_controller.ex                                                                                                                   
* creating test/auth_web/controllers/user_registration_controller_test.exs                                                                                                            
* creating lib/auth_web/views/user_registration_view.ex                                    
* creating lib/auth_web/views/user_reset_password_view.ex                                  
* creating lib/auth_web/controllers/user_reset_password_controller.ex                                                                                                                 
* creating test/auth_web/controllers/user_reset_password_controller_test.exs                                                                                                          
* creating lib/auth_web/templates/user_reset_password/edit.html.heex                                                                                                                  
* creating lib/auth_web/templates/user_reset_password/new.html.heex                                                                                                                   
* creating lib/auth_web/views/user_session_view.ex                                         
* creating lib/auth_web/controllers/user_session_controller.ex                             
* creating test/auth_web/controllers/user_session_controller_test.exs                                                                                                                 
* creating lib/auth_web/templates/user_session/new.html.heex                               
* creating lib/auth_web/views/user_settings_view.ex                                        
* creating lib/auth_web/templates/user_settings/edit.html.heex                             
* creating lib/auth_web/controllers/user_settings_controller.ex                            
* creating test/auth_web/controllers/user_settings_controller_test.exs                                                                                                                
* creating lib/auth/accounts.ex              
* injecting lib/auth/accounts.ex             
* creating test/auth/accounts_test.exs                                                     
* injecting test/auth/accounts_test.exs                                                    
* creating test/support/fixtures/accounts_fixtures.ex                                      
* injecting test/support/fixtures/accounts_fixtures.ex                                     
* injecting test/support/conn_case.ex                                                      
* injecting config/test.exs                  
* injecting mix.exs                          
* injecting lib/auth_web/router.ex                                                         
* injecting lib/auth_web/router.ex - imports                                               
* injecting lib/auth_web/router.ex - plug                                                  
* injecting lib/auth_web/templates/layout/root.html.heex                                   
Please re-fetch your dependencies with the following command:                              

    $ mix deps.get                           

Remember to update your repository by running migrations:                                  

    $ mix ecto.migrate                       

Once you are ready, visit "/users/register"                                                
to create your account and then access "/dev/mailbox" to                                   
see the account confirmation email.                                                        

[agreif@nixos:~/project/phx-auth]$ mix deps.get                                            

Resolving Hex dependencies...                
Dependency resolution completed:                                                           
Unchanged:                                   
  castore 0.1.18                             
  connection 1.1.0                           
  cowboy 2.9.0                               
  cowboy_telemetry 0.4.0                     
  cowlib 2.11.0                              
  db_connection 2.4.2                        
  decimal 2.0.0                              
  ecto 3.8.4                                 
  ecto_sql 3.8.3                             
  esbuild 0.5.0                              
  file_system 0.2.10                         
  floki 0.33.1                               
  gettext 0.20.0                             
  html_entities 0.5.2                        
  jason 1.4.0                                
  mime 2.0.3                                 
  phoenix 1.6.12                             
  phoenix_ecto 4.4.0                         
  phoenix_html 3.2.0                         
  phoenix_live_dashboard 0.6.5               
  phoenix_live_reload 1.3.3                  
  phoenix_live_view 0.17.12                  
  phoenix_pubsub 2.1.1                       
  phoenix_view 1.1.2                         
  plug 1.13.6                                
  plug_cowboy 2.5.2                          
  plug_crypto 1.2.3                          
  postgrex 0.16.5                            
  ranch 1.8.0                                
  swoosh 1.8.0                               
  telemetry 1.1.0                            
  telemetry_metrics 0.6.1                    
  telemetry_poller 1.0.0                     
New:                                         
  bcrypt_elixir 3.0.1                        
  comeonin 5.3.3                             
  elixir_make 0.6.3                          
* Getting bcrypt_elixir (Hex package)                                                      
* Getting comeonin (Hex package)                                                           
* Getting elixir_make (Hex package)                                                        

[agreif@nixos:~/project/phx-auth]$ mix ecto.migrate                                        

09:02:13.135 [info]  == Running 20220922070058 Auth.Repo.Migrations.CreateUsersAuthTables.change/0 forward                                                                            

09:02:13.158 [info]  execute "CREATE EXTENSION IF NOT EXISTS citext"                                                                                                                  

09:02:13.159 [info]  extension "citext" already exists, skipping                                                                                                                      

09:02:13.159 [info]  create table users                                                    

09:02:13.219 [info]  create index users_email_index                                        

09:02:13.241 [info]  create table users_tokens                                             

09:02:13.257 [info]  create index users_tokens_user_id_index                               

09:02:13.261 [info]  create index users_tokens_context_token_index                                                                                                                    

09:02:13.285 [info]  == Migrated 20220922070058 in 0.1s                                    

started server

[agreif@nixos:~/project/phx-auth]$ mix phx.server                                                                                                                           [530/1914]
[info] Running AuthWeb.Endpoint with cowboy 2.9.0 at 127.0.0.1:4000 (http)                                                                                                            
[info] Access AuthWeb.Endpoint at http://localhost:4000                                                                                                                               
[watch] build finished, watching for changes...                                                                                                                                       
[info] GET /users/log_in                                                                                                                                                              
[debug] Processing with AuthWeb.UserSessionController.new/2                                                                                                                           
  Parameters: %{}                                                                                                                                                                     
  Pipelines: [:browser, :redirect_if_user_is_authenticated]                                                                                                                           
[info] Sent 200 in 345ms                                                                                                                                                              
[info] GET /users/log_in                                                                                                                                                              [debug] Processing with AuthWeb.UserSessionController.new/2                                                                                                                             Parameters: %{}                                                                                                                                                                       Pipelines: [:browser, :redirect_if_user_is_authenticated]                                                                                                                           
[info] Sent 200 in 28ms                                                                                                                                                               
[info] GET /users/log_in                                                                                                                                                              [debug] Processing with AuthWeb.UserSessionController.new/2                                                                                                                             Parameters: %{}                                                                                                                                                                       Pipelines: [:browser, :redirect_if_user_is_authenticated]                                                                                                                           
[info] Sent 200 in 43ms                                                                                                                                                               
[info] GET /users/log_in                                                                                                                                                              [debug] Processing with AuthWeb.UserSessionController.new/2                                                                                                                             Parameters: %{}                                                                                                                                                                       Pipelines: [:browser, :redirect_if_user_is_authenticated]                                                                                                                           
[debug] Duplicate channel join for topic "phoenix:live_reload" in Phoenix.LiveReloader.Socket. Closing existing channel for new join.                                                 
[info] Sent 200 in 25ms                                                                                                                                                               
[info] GET /users/log_in                                                                                                                                                              
[debug] Processing with AuthWeb.UserSessionController.new/2                                                                                                                             Parameters: %{}                                                                                                                                                                       Pipelines: [:browser, :redirect_if_user_is_authenticated]                                                                                                                           
[info] Sent 200 in 39ms                                                                                                                                                               
[info] GET /users/log_in                                                                                                                                                              [debug] Processing with AuthWeb.UserSessionController.new/2                                                                                                                             Parameters: %{}                                                                                                                                                                       Pipelines: [:browser, :redirect_if_user_is_authenticated]                                                                                                                           
[info] Sent 200 in 30ms                                                                                                                                                               
[info] GET /users/log_in                                                                                                                                                              
...
[info] GET /users/log_in                                                                                                                                                    [450/1914]
[debug] Processing with AuthWeb.UserSessionController.new/2
  Parameters: %{}
  Pipelines: [:browser, :redirect_if_user_is_authenticated]
[debug] Duplicate channel join for topic "phoenix:live_reload" in Phoenix.LiveReloader.Socket. Closing existing channel for new join.
[info] Sent 500 in 277ms
[error] #PID<0.783.0> running AuthWeb.Endpoint (connection #PID<0.535.0>, stream id 15) terminated
Server: localhost:4000 (http)
Request: GET /users/log_in
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function Phoenix.HTML.FormData.to_form/2 is undefined or private
        (phoenix_html 3.2.0) Phoenix.HTML.FormData.to_form(%Plug.Conn{adapter: {Plug.Cowboy.Conn, :...}, assigns: %{current_user: nil, error_message: nil, layout: {AuthWeb.LayoutView
, "app.html"}}, body_params: %{}, cookies: %{"NAS_PW_STATUS" => "0", "QMonitor" => "1657177331274", "QT" => "1657185725273", "XSRF-TOKEN" => "RJuVco9uTI", "__profilin" => "p%3Dt", "_
auth_key" => "...","_demo_key" => "...", "id" => "Av5xUQgj46FRAtW2vb2p4CAC2o5JY0IvMU9slkvsxSAtENI
FVpCsyDX51c0bpH0qAnvBrFtHbwvdhZEV4wS4Ck", "showAllAp" => "true", "smid" => "..."}, halted: false, h
ost: "localhost", method: "GET", owner: #PID<0.783.0>, params: %{}, path_info: ["users", "log_in"], path_params: %{}, port: 4000, private: %{AuthWeb.Router => {[], %{Plug.Swoosh.Mail
boxPreview => ["mailbox"]}}, :before_send => [#Function<0.16477574/1 in Plug.CSRFProtection.call/2>, #Function<2.17183421/1 in Phoenix.Controller.fetch_flash/2>, #Function<0.77458138
/1 in Plug.Session.before_send/2>, #Function<0.23023616/1 in Plug.Telemetry.call/2>, #Function<1.120844262/1 in Phoenix.LiveReloader.before_send_inject_reloader/3>], :phoenix_action 
=> :new, :phoenix_controller => AuthWeb.UserSessionController, :phoenix_endpoint => AuthWeb.Endpoint, :phoenix_flash => %{}, :phoenix_format => "html", :phoenix_layout => {AuthWeb.La
youtView, :app}, :phoenix_request_logger => {"request_logger", "request_logger"}, :phoenix_root_layout => {AuthWeb.LayoutView, :root}, :phoenix_router => AuthWeb.Router, :phoenix_tem
plate => "new.html", :phoenix_view => AuthWeb.UserSessionView, :plug_session => %{"_csrf_token" => "B8Q9ppcwo6jE8i2ECWpiEztW"}, :plug_session_fetch => :done}, query_params: %{}, quer
y_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %{"NAS_PW_STATUS" => "0", "QMonitor" => "1657177331274", "QT" => "1657185725273", "XSRF-TOKEN" => "RJuVco9uTI", "__profilin" => 
"p%3Dt", "_auth_key" => "...", ... (truncate
d)
[info] GET /users/log_in
[debug] Processing with AuthWeb.UserSessionController.new/2
  Parameters: %{}
  Pipelines: [:browser, :redirect_if_user_is_authenticated]
[info] Sent 200 in 21ms
[info] GET /users/log_in
[debug] Processing with AuthWeb.UserSessionController.new/2
  Parameters: %{}
  Pipelines: [:browser, :redirect_if_user_is_authenticated]
[info] Sent 200 in 40ms
josevalim commented 2 years ago

Are you using an editor with automatic compilation or anything that could be trying to compile things behind the scenes and therefore affecting the results?

If so, try using only mix phx.server from the terminal and see if the issue persists.

agreif commented 2 years ago

Hi I am working via ssh on a headless server where I edit files with emacs directly from the command line. As you can see in my last log post I aready start the server with 'mix phx.server'. You should be able to reproduce it with the steps I gave. Just setup a simple project, add the auth, start the server and reload the login page repeatedly in a fast pace.

m4hi2 commented 2 years ago

@agreif I've followed the steps you've taken but couldn't reproduce the error. I've refreshed by repeatedly pressing the "F5" key, but it loaded each time properly.

Like Jose has already mentioned, it might be that you have some LSP helper setup with emacs and it can cause some issues. Can you please run rm -rf _build and then run mix compile && mix phx.server without opening files with emacs?

Note: I've tested with the same exact Elixir/OTP and Phoenix version as you. The only difference is the OS, I've used Ubuntu 20.04

josevalim commented 2 years ago

Thank you @m4hi2 for looking into it!

agreif commented 2 years ago

@m4hi2 I did 'rm -rf _build && mix compile && mix phx.server' and now it took longer, but calling 'http://localhost:4000/users/log_in' in the browser and Ctrl-R about 100 times brought the error.

agreif commented 2 years ago

@m4hi2 emacs was closed, so this is not the reason and nothing else is changing files in the directory. The error (UndefinedFunctionError) function Phoenix.HTML.FormData.to_form/2 is undefined or private still happens. Its really weird, because it sometimes happens after a few reloads and sometimes (as above) after 100 reloads.

josevalim commented 2 years ago

Oh! What is the ulimit in your system? Have you tried bumping it up?

Sometimes Erlang cannot load modules because of ulimit...

agreif commented 2 years ago
[root@nixos:~]#  ulimit -n
1024

which value is suggested?

m4hi2 commented 2 years ago

I used for x in $(seq 1000); do curl http://localhost:4000/users/log_in > /dev/null ; done on a separate terminal window while keeping an eye on the window that is running the phx.server but haven't encountered any errors. This is no scientific test by any means, for that we'd have to resort to tools like Playwright I think.

BTW, I've the same ulimit value of 1024 on my system.

m4hi2 commented 2 years ago

Sometimes Erlang cannot load modules because of limit...

But since it's sometimes working and only after a while it's not working, doesn't it mean that the modules are already loaded? 🤔

josevalim commented 2 years ago

Please try setting it to unlimited or quadrupling it just in case.

agreif commented 2 years ago

[root@nixos:~]# ulimit -n 65565

even now, after reloading for 20 secs the error happens :(

theenglishway commented 2 years ago

Hi all !

I've been hitting the exact same problem as @agreif a good number of times while doing personal stuff with Phoenix Live-View over the last months (or last year ?), but due to its spurious nature I never bothered to turn it into an issue.. It seemed totally random to me, though occurring quite often.

At the moment I'm running Erlang/OTP 25 and Elixir v1.14.0 (installed under ArchLinux using asdf) but I run into the same problem with older versions of Elixir / Erlang (1.13.x and OTP 24 and maybe even with a 1.12.x or under Debian but I could not swear).

I'm running a VERY simple toy application which I could totally share if that turned useful. I've tried the suggestions posted in this thread : deleting _build, closing my IDE (VS Code with extensions related to Elixir language), ... to no effect.

At the moment, I can reproduce the bug with 100% reliability by simply launching the dev server of that app with and navigating to localhost:4000 in Firefox.

I have noticed some interesting patterns though, of which an expert eye might make some sense :

In the setup I describe where the server is started with --erl "+S 1", changing ulimit -n does not seem to have any effect. Setting it to 1024 or to the highest value (524_288 on my system) did not change anything, and it kept on crashing every time but the first in both cases.

I'll add that for some reason, I've been using this "+S 1" flag a lot, and it's very, very likely that I was using it all the times I saw that problem occur over the last few months.

Hope that can help, and tell me if you have any suggestion of test I could do or additional information I could give

chrismccord commented 1 year ago

If folks can provide more information on this it would be helpful, but I don't believe it's an issue on our side. Thanks!

theenglishway commented 1 year ago

@chrismccord The issue is still happening here, with 100% reliable reproducibility on the project I am currently working on, when I run it with iex --erl "+S 1" -S mix phx.server.

This does not seem specifically related to Phoenix indeed since on my other project it may also throw such a random error with some other protocol, e.g. Phoenix.HTML.Safe or Ecto.Queryable.

As I said in a previous comment, I'm willing to help sort the issue and provide some additional information, test other scenarios, or fill a bug report in another repo (Elixir itself ?), but as of today I really don't have the expertise to provide a minimal project that reproduces the issue as reliably as on my project (which I won't share).

What I can say though is that if I follow the procedure that @agreif described in a comment above, the bug will occur quite often on my machine (though not very reliably : about once every five or ten page refresh).

My setup :

$ elixir -v
Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]

Elixir 1.14.2 (compiled with Erlang/OTP 25)

$ mix phx.new --version
Phoenix installer v1.7.0-rc.0

(my personal project uses the same versions)

Steps I followed :

mix phx.new form_bug --database sqlite3
cd form_bug
mix ecto.create
mix phx.gen.auth Accounts User users
mix deps.get
mix ecto.migrate 

Then run the server with iex --erl "+S 1" -S mix phx.server, go to http://localhost:4000/ and click like a maniac on the "Register" link (it makes the bug occur more reliably than refreshing the page with F5).

After 5/10 times, the following error message appears :

# UndefinedFunctionError at GET /users/register

Exception:

    ** (UndefinedFunctionError) function Phoenix.HTML.FormData.to_form/2 is undefined (module Phoenix.HTML.FormData is not available)
        (phoenix_html 3.2.0) Phoenix.HTML.FormData.to_form(#Ecto.Changeset&lt;action: nil, changes: %{}, errors: [password: {"can't be blank", [validation: :required]}, email: {"can't be blank", [validation: :required]}], data: #FormBug.Accounts.User&lt;&gt;, valid?: false&gt;, [as: :user, errors: [], id: "registration_form", method: "post", multipart: false, "phx-change": "validate", "phx-submit": "save", "phx-trigger-action": false])
        (phoenix_live_view 0.18.3) lib/phoenix_component.ex:1939: Phoenix.Component."form (overridable 1)"/1
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/html_engine.ex:35: Phoenix.LiveView.HTMLEngine.component/3
        (form_bug 0.1.0) lib/form_bug_web/components/core_components.ex:193: anonymous fn/2 in FormBugWeb.CoreComponents."simple_form (overridable 1)"/1
        (form_bug 0.1.0) /home/theenglishway/Documents/dev/form_bug/lib/form_bug_web/live/user_registration_live.ex:21: FormBugWeb.UserRegistrationLive.render/1
        (elixir 1.14.2) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/diff.ex:387: Phoenix.LiveView.Diff.traverse/7
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/diff.ex:521: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
        (elixir 1.14.2) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/diff.ex:387: Phoenix.LiveView.Diff.traverse/7
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/diff.ex:138: Phoenix.LiveView.Diff.render/3
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/static.ex:244: Phoenix.LiveView.Static.to_rendered_content_tag/4
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/static.ex:127: Phoenix.LiveView.Static.render/3
        (phoenix_live_view 0.18.3) lib/phoenix_live_view/controller.ex:39: Phoenix.LiveView.Controller.live_render/3
        (phoenix 1.7.0-rc.0) lib/phoenix/router.ex:425: Phoenix.Router.__call__/2
        (form_bug 0.1.0) lib/form_bug_web/endpoint.ex:1: FormBugWeb.Endpoint.plug_builder_call/2
        (form_bug 0.1.0) lib/plug/debugger.ex:136: FormBugWeb.Endpoint."call (overridable 3)"/2
        (form_bug 0.1.0) lib/form_bug_web/endpoint.ex:1: FormBugWeb.Endpoint.call/2

Code:

`nofile`

    No code available.

  Called with 2 arguments

  * `#Ecto.Changeset&lt;action: nil, changes: %{}, errors: [password: {"can't be blank", [validation: :required]}, email: {"can't be blank", [validation: :required]}], data: #FormBug.Accounts.User&lt;&gt;, valid?: false&gt;`
  * `[as: :user, errors: [], id: "registration_form", method: "post", multipart: false, "phx-change": "validate", "phx-submit": "save", "phx-trigger-action": false]`

  Attempted function clauses (showing 1 out of 1)

     def to_form(term, arg2)

`lib/phoenix_component.ex`

    1934       form_options = assigns_to_attributes(Map.merge(assigns, assigns.rest), [:action, :for, :rest])
    1935   
    1936       # Since FormData may add options, read the actual options from form
    1937       %{options: opts} =
    1938         form = %Phoenix.HTML.Form{
    1939&gt;          Phoenix.HTML.FormData.to_form(form_for, form_options)
    1940           | action: action || "#"
    1941         }
    1942   
    1943       # By default, we will ignore action, method, and csrf token
    1944       # unless the action is given.

`lib/phoenix_live_view/html_engine.ex`

    30         case assigns do
    31           %{__changed__: _} -&gt; assigns
    32           _ -&gt; assigns |&gt; Map.new() |&gt; Map.put_new(:__changed__, nil)
    33         end
    34   
    35&gt;      case func.(assigns) do
    36         %Phoenix.LiveView.Rendered{} = rendered -&gt;
    37           %{rendered | caller: caller}
    38   
    39         %Phoenix.LiveView.Component{} = component -&gt;
    40           component

`lib/form_bug_web/components/core_components.ex`

    188     slot :inner_block, required: true
    189     slot :actions, doc: "the slot for form actions, such as a submit button"
    190   
    191     def simple_form(assigns) do
    192       ~H"""
    193&gt;      &lt;.form :let={f} for={@for} as={@as} {@rest}&gt;
    194         &lt;div class="space-y-8 bg-white mt-10"&gt;
    195           &lt;%= render_slot(@inner_block, f) %&gt;
    196           &lt;div :for={action &lt;- @actions} class="mt-2 flex items-center justify-between gap-6"&gt;
    197             &lt;%= render_slot(action, f) %&gt;
    198           &lt;/div&gt;

`/home/theenglishway/Documents/dev/form_bug/lib/form_bug_web/live/user_registration_live.ex`

    16             &lt;/.link&gt;
    17             to your account now.
    18           &lt;/:subtitle&gt;
    19         &lt;/.header&gt;
    20   
    21&gt;        &lt;.simple_form
    22           :let={f}
    23           id="registration_form"
    24           for={@changeset}
    25           phx-submit="save"
    26           phx-change="validate"

`lib/enum.ex`

    No code available.

`lib/phoenix_live_view/diff.ex`

    382            components,
    383            template,
    384            changed?
    385          ) do
    386       {_counter, diff, children, pending, components, template} =
    387&gt;        traverse_dynamic(socket, invoke_dynamic(rendered, false), %{}, pending, components, template, changed?)
    388   
    389       {diff, template} = maybe_template_static(diff, fingerprint, static, template)
    390       {diff, {fingerprint, children}, pending, components, template}
    391     end
    392   

`lib/phoenix_live_view/diff.ex`

    516       Enum.reduce(dynamic, {0, %{}, children, pending, components, template}, fn
    517         entry, {counter, diff, children, pending, components, template} -&gt;
    518           child = Map.get(children, counter)
    519   
    520           {serialized, child_fingerprint, pending, components, template} =
    521&gt;            traverse(socket, entry, child, pending, components, template, changed?)
    522   
    523           # If serialized is nil, it means no changes.
    524           # If it is an empty map, then it means it is a rendered struct
    525           # that did not change, so we don't have to emit it either.
    526           diff =

`lib/enum.ex`

    No code available.

`lib/phoenix_live_view/diff.ex`

    382            components,
    383            template,
    384            changed?
    385          ) do
    386       {_counter, diff, children, pending, components, template} =
    387&gt;        traverse_dynamic(socket, invoke_dynamic(rendered, false), %{}, pending, components, template, changed?)
    388   
    389       {diff, template} = maybe_template_static(diff, fingerprint, static, template)
    390       {diff, {fingerprint, children}, pending, components, template}
    391     end
    392   

`lib/phoenix_live_view/diff.ex`

    133       render(%{socket | fingerprints: new_fingerprints()}, rendered, new_components(uuids))
    134     end
    135   
    136     def render(%{fingerprints: prints} = socket, %Rendered{} = rendered, components) do
    137       {diff, prints, pending, components, nil} =
    138&gt;        traverse(socket, rendered, prints, %{}, components, nil, true)
    139   
    140       # cid_to_component is used by maybe_reuse_static and it must be a copy before changes.
    141       # However, given traverse does not change cid_to_component, we can read it now.
    142       {cid_to_component, _, _} = components
    143   

`lib/phoenix_live_view/static.ex`

    239       {:safe, dynamic_tag_to_iodata(tag, attrs, "")}
    240     end
    241   
    242     defp to_rendered_content_tag(socket, tag, view, attrs) do
    243       rendered = Utils.to_rendered(socket, view)
    244&gt;      {_, diff, _} = Diff.render(socket, rendered, Diff.new_components())
    245       {:safe, dynamic_tag_to_iodata(tag, attrs, {:safe, Diff.to_iodata(diff)})}
    246     end
    247   
    248     defp dynamic_tag_to_iodata(tag, attrs, content) do
    249       assigns = %{tag: tag, attrs: attrs, content: content}

`lib/phoenix_live_view/static.ex`

    122             {:data, data_attrs}
    123             | extended_attrs
    124           ]
    125   
    126           try do
    127&gt;            {:ok, to_rendered_content_tag(socket, tag, view, attrs), socket.assigns}
    128           catch
    129             :throw, {:phoenix, :child_redirect, redirected, flash} -&gt;
    130               {:stop, Utils.replace_flash(%{socket | redirected: redirected}, flash)}
    131           end
    132   

`lib/phoenix_live_view/controller.ex`

    34           end
    35         end
    36   
    37     """
    38     def live_render(%Plug.Conn{} = conn, view, opts \\ []) do
    39&gt;      case LiveView.Static.render(conn, view, opts) do
    40         {:ok, content, socket_assigns} -&gt;
    41           conn
    42           |&gt; Phoenix.Controller.put_view(LiveView.Static)
    43           |&gt; Phoenix.Controller.render(
    44             "template.html",

`lib/phoenix/router.ex`

    420           :telemetry.execute([:phoenix, :router_dispatch, :stop], measurements, metadata)
    421           halted_conn
    422   
    423         %Plug.Conn{} = piped_conn -&gt;
    424           try do
    425&gt;            plug.call(piped_conn, plug.init(opts))
    426           else
    427             conn -&gt;
    428               measurements = %{duration: System.monotonic_time() - start}
    429               metadata = %{metadata | conn: conn}
    430               :telemetry.execute([:phoenix, :router_dispatch, :stop], measurements, metadata)

`lib/form_bug_web/endpoint.ex`

    1&gt;  defmodule FormBugWeb.Endpoint do
    2     use Phoenix.Endpoint, otp_app: :form_bug
    3   
    4     # The session will be stored in the cookie and signed,
    5     # this means its contents can be read but not tampered with.
    6     # Set :encryption_salt if you would also like to encrypt it.

`lib/plug/debugger.ex`

    No code available.

`lib/form_bug_web/endpoint.ex`

    1&gt;  defmodule FormBugWeb.Endpoint do
    2     use Phoenix.Endpoint, otp_app: :form_bug
    3   
    4     # The session will be stored in the cookie and signed,
    5     # this means its contents can be read but not tampered with.
    6     # Set :encryption_salt if you would also like to encrypt it.

## Connection details

### Params

    %{}

### Request info

  * URI: http://localhost:4000/users/register
  * Query string: 

### Headers

  * accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
  * accept-encoding: gzip, deflate, br
  * accept-language: en-US,en;q=0.5
  * connection: keep-alive
  * cookie: _form_bug_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYdGlGLVFEclNkWUtWYmRKYTA4bU41eGIt.aIup6z3SlZouKIKcFQ-Ia4mfpjsXGr5HFSMG55Ff9gg
  * host: localhost:4000
  * referer: http://localhost:4000/users/register
  * sec-fetch-dest: document
  * sec-fetch-mode: navigate
  * sec-fetch-site: same-origin
  * sec-fetch-user: ?1
  * upgrade-insecure-requests: 1
  * user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0

### Session

    %{"_csrf_token" =&gt; "tiF-QDrSdYKVbdJa08mN5xb-"}

Running the server with the "+S 1" flag makes a huge difference (the bug does not seem to happen with +S 2 or +S 4).

ev94 commented 1 year ago

Hi,

I've encountered the same issue. It was due to inconsistent dependencies. I solved it by upgrading all the deps.