albin

albin

On a fresh project with ash_authentication installed, an insert into the user table triggers a rollback. However, it works fine for other simple resources.

[info] GET /register
[debug] Processing with AshAuthentication.Phoenix.SignInLive.register/2
  Parameters: %{}
  Pipelines: [:browser]
[info] Sent 200 in 3ms
[info] CONNECTED TO Phoenix.LiveView.Socket in 13µs
  Transport: :websocket
  Serializer: Phoenix.Socket.V2.JSONSerializer
  Parameters: %{"_csrf_token" => "WQAnQHAKB3MZCgFGClQUGxkoFCQoK38L-qh2AgKDObo2MeZOoxywNRGA", "_live_referer" => "undefined", "_mount_attempts" => "0", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
[debug] MOUNT AshAuthentication.Phoenix.SignInLive
  Parameters: %{}
  Session: %{"_csrf_token" => "tqOr1mL7VhntG1NTvPmSfy8J", "auth_routes_prefix" => "/auth", "context" => nil, "gettext_fn" => nil, "otp_app" => nil, "overrides" => [AshEventsTestWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], "path" => "/sign-in", "register_path" => "/register", "reset_path" => "/reset", "resources" => nil, "tenant" => nil}
[debug] Replied in 122µs
[debug] HANDLE PARAMS in AshAuthentication.Phoenix.SignInLive
  Parameters: %{}
[debug] Replied in 11µs
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "JD57KkslfGQ1BDg7BHQ7GhMCOzxXGlEkPO4XzH0SclVOCEuNeRVo1cin", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "haha@lol.", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "JD57KkslfGQ1BDg7BHQ7GhMCOzxXGlEkPO4XzH0SclVOCEuNeRVo1cin", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "haha@lol.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "JD57KkslfGQ1BDg7BHQ7GhMCOzxXGlEkPO4XzH0SclVOCEuNeRVo1cin", "_target" => ["user", "password"], "user" => %{"_unused_password_confirmation" => "[FILTERED]", "email" => "haha@lol.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "JD57KkslfGQ1BDg7BHQ7GhMCOzxXGlEkPO4XzH0SclVOCEuNeRVo1cin", "_target" => ["user", "password_confirmation"], "user" => %{"email" => "haha@lol.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "submit" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "JD57KkslfGQ1BDg7BHQ7GhMCOzxXGlEkPO4XzH0SclVOCEuNeRVo1cin", "user" => %{"email" => "haha@lol.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] QUERY OK db=0.6ms idle=1283.2ms
begin []
↳ anonymous fn/3 in Ash.Changeset.with_hooks/3, at: lib/ash/changeset/changeset.ex:3760
[debug] QUERY OK db=0.5ms
SELECT pg_advisory_xact_lock($1) [2147483647]
[debug] QUERY OK source="events" db=2.0ms
INSERT INTO "events" ("data","version","metadata","resource","action","action_type","occurred_at","record_id") VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING "user_id","record_id","occurred_at","system_actor","action_type","action","resource","metadata","version","data","id" [%{password: "asdfasdf", email: #Ash.CiString<"haha@lol.com">, password_confirmation: "asdfasdf"}, 1, %{}, AshEventsTest.Accounts.User, :register_with_password, :create, ~U[2025-05-24 16:13:04.472551Z], "f4e3ef2d-2f6d-48e5-ba52-7bc4a7c26017"]
↳ AshPostgres.DataLayer.bulk_create/3, at: lib/data_layer.ex:1979
[debug] QUERY OK db=0.5ms
rollback []
↳ anonymous fn/3 in Ash.Changeset.with_hooks/3, at: lib/ash/changeset/changeset.ex:3760
[debug] Replied in 15ms

To Reproduce
Here’s a minimal reproduction of the issue: GitHub - albinkc/ash_events_test · GitHub

Expected behavior
An Error stating the reason for the transaction rollback.

** Runtime

  • Erlang/OTP 27 [erts-15.2.7] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]

  • Elixir 1.18.3 (compiled with Erlang/OTP 27)

  • MacOS 15.5

Additional context
FWIW, Tried on both PG 17 and 18

Showing Posts 1 to 10

zachdaniel

zachdaniel

Creator of Ash

Are there any log messages showing warnings for unhandled errors?

zachdaniel

zachdaniel

Creator of Ash

Definitely something strange.

zachdaniel

zachdaniel

Creator of Ash

I will have to look in a few days. Does the error go away if you don’t use ash_events?

albin

albin OP

yes, without ash_events, adding a user via /register or via ash_admin works as expected

zachdaniel

zachdaniel

Creator of Ash

Interesting. Perhaps @Torkan will have a chance to look into this? Otherwise, I will look at the repro in a few days.

albin

albin OP

nothing I could find in the logs. Here’s the full log:

albin@Albins-MacBook-Pro:~/projects/a/ash_events_test/ > mix phx.server
[info] Running LiveDebuggerWeb.Endpoint with Bandit 1.6.11 at 127.0.0.1:4007 (http)
[info] Access LiveDebuggerWeb.Endpoint at http://localhost:4007
[info] Running AshEventsTestWeb.Endpoint with Bandit 1.6.11 at 127.0.0.1:4000 (http)
[info] Access AshEventsTestWeb.Endpoint at http://localhost:4000
[watch] build finished, watching for changes...

Rebuilding...

Done in 213ms.
[info] CONNECTED TO Phoenix.LiveView.Socket in 16µs
  Transport: :longpoll
  Serializer: Phoenix.Socket.V2.JSONSerializer
  Parameters: %{"_csrf_token" => "WQAnQHAKB3MZCgFGClQUGxkoFCQoK38L-qh2AgKDObo2MeZOoxywNRGA", "_live_referer" => "undefined", "_mount_attempts" => "0", "_mounts" => "5", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
[debug] MOUNT AshAuthentication.Phoenix.SignInLive
  Parameters: %{}
  Session: %{"_csrf_token" => "tqOr1mL7VhntG1NTvPmSfy8J", "auth_routes_prefix" => "/auth", "context" => nil, "gettext_fn" => nil, "otp_app" => nil, "overrides" => [AshEventsTestWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], "path" => "/sign-in", "register_path" => "/register", "reset_path" => "/reset", "resources" => nil, "tenant" => nil}
[debug] Replied in 273µs
[debug] HANDLE PARAMS in AshAuthentication.Phoenix.SignInLive
  Parameters: %{}
[debug] Replied in 16µs
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.SignInForm
  Parameters: %{"_csrf_token" => "JkQsK3UeDk97IxsRDUMbLBc3Wh0lI34yR5cYDsBx-KueJrUxag7NCZFx", "_target" => ["user", "email"], "user" => %{"_unused_email" => "", "_unused_password" => "[FILTERED]", "email" => "", "password" => "[FILTERED]"}}
[debug] Replied in 431µs
[info] GET /register
[debug] Processing with AshAuthentication.Phoenix.SignInLive.register/2
  Parameters: %{}
  Pipelines: [:browser]
[info] Sent 200 in 2ms
[info] CONNECTED TO Phoenix.LiveView.Socket in 12µs
  Transport: :websocket
  Serializer: Phoenix.Socket.V2.JSONSerializer
  Parameters: %{"_csrf_token" => "P1x6HFwpHU4jODkaFXx_ODwmWSFLTk4mK-5nmDQyuPWnRM1lJv4r-7vl", "_live_referer" => "undefined", "_mount_attempts" => "0", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
[debug] MOUNT AshAuthentication.Phoenix.SignInLive
  Parameters: %{}
  Session: %{"_csrf_token" => "tqOr1mL7VhntG1NTvPmSfy8J", "auth_routes_prefix" => "/auth", "context" => nil, "gettext_fn" => nil, "otp_app" => nil, "overrides" => [AshEventsTestWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], "path" => "/sign-in", "register_path" => "/register", "reset_path" => "/reset", "resources" => nil, "tenant" => nil}
[debug] Replied in 110µs
[debug] HANDLE PARAMS in AshAuthentication.Phoenix.SignInLive
  Parameters: %{}
[debug] Replied in 31µs
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "he", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "hello", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "hello@", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 2ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "hello@h", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "hello@he", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 2ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "hello@hello.", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 2ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "hello@hello.c", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 2ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "email"], "user" => %{"_unused_password" => "[FILTERED]", "_unused_password_confirmation" => "[FILTERED]", "email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "password"], "user" => %{"_unused_password_confirmation" => "[FILTERED]", "email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 2ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "password"], "user" => %{"_unused_password_confirmation" => "[FILTERED]", "email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 2ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "password_confirmation"], "user" => %{"email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "password_confirmation"], "user" => %{"email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 2ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "password_confirmation"], "user" => %{"email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 3ms
[debug] HANDLE EVENT "change" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "_target" => ["user", "password"], "user" => %{"email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] Replied in 1ms
[debug] HANDLE EVENT "submit" in AshAuthentication.Phoenix.SignInLive
  Component: AshAuthentication.Phoenix.Components.Password.RegisterForm
  Parameters: %{"_csrf_token" => "MjgAQkUmFVUyKiEiFlkYIAIHW34wIWx7FIO0tKYbdBOVQhVttW6-VXT1", "user" => %{"email" => "hello@hello.com", "password" => "[FILTERED]", "password_confirmation" => "[FILTERED]"}}
[debug] QUERY OK db=0.7ms queue=0.1ms idle=38.9ms
begin []
↳ anonymous fn/3 in Ash.Changeset.with_hooks/3, at: lib/ash/changeset/changeset.ex:3760
[debug] QUERY OK db=0.7ms
SELECT pg_advisory_xact_lock($1) [2147483647]
[debug] QUERY OK source="events" db=5.1ms
INSERT INTO "events" ("data","version","metadata","resource","action","action_type","occurred_at","record_id") VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING "user_id","record_id","occurred_at","system_actor","action_type","action","resource","metadata","version","data","id" [%{password: "asdfasdf5", email: #Ash.CiString<"hello@hello.com">, password_confirmation: "asdfasdf5"}, 1, %{}, AshEventsTest.Accounts.User, :register_with_password, :create, ~U[2025-05-25 02:12:01.604625Z], "aead8b9f-482c-4b41-85f2-a1bfdda855d8"]
↳ AshPostgres.DataLayer.bulk_create/3, at: lib/data_layer.ex:1979
[debug] QUERY OK db=0.4ms
rollback []
↳ anonymous fn/3 in Ash.Changeset.with_hooks/3, at: lib/ash/changeset/changeset.ex:3760
[debug] Replied in 22ms
albin

albin OP

OK, when I clicked create on User resource in Ash Admin, the page froze for about 5-10 seconds and then gave me this error:

# Ash.Error.Unknown at GET /admin

Exception:

    ** (Ash.Error.Unknown) 
    Bread Crumbs:
      > action change {AshAuthentication.Strategy.MagicLink.SignInChange, []}
      > building changeset for AshEventsTest.Accounts.User.sign_in_with_magic_link_ash_events_orig_impl
      
    
    Unknown Error
    
    * ** (RuntimeError) No strategy action named `:sign_in_with_magic_link_ash_events_orig_impl` found on resource `AshEventsTest.Accounts.User`
      (ash_authentication 4.8.7) lib/ash_authentication/info.ex:68: AshAuthentication.Info.strategy_for_action!/2
      (ash_authentication 4.8.7) lib/ash_authentication/strategies/magic_link/sign_in_change.ex:19: AshAuthentication.Strategy.MagicLink.SignInChange.change/3
      (ash 3.5.12) lib/ash/changeset/changeset.ex:2841: Ash.Changeset.run_change_or_validation/6
      (ash 3.5.12) lib/ash/changeset/changeset.ex:2700: anonymous fn/6 in Ash.Changeset.run_action_changes/6
      (elixir 1.18.3) lib/enum.ex:2546: Enum."-reduce/3-lists^foldl/2-0-"/3
      (ash 3.5.12) lib/ash/changeset/changeset.ex:2696: Ash.Changeset.run_action_changes/6
      (ash 3.5.12) lib/ash/changeset/changeset.ex:2167: Ash.Changeset.do_for_action/4
      (ash_phoenix 2.3.2) lib/ash_phoenix/form/form.ex:603: AshPhoenix.Form.for_create/3
      (ash_admin 0.13.5) lib/ash_admin/components/resource/form.ex:2203: AshAdmin.Components.Resource.Form.assign_form/1
      (ash_admin 0.13.5) lib/ash_admin/components/resource/form.ex:38: AshAdmin.Components.Resource.Form.update/2
      (phoenix_live_view 1.0.12) lib/phoenix_live_view/utils.ex:492: Phoenix.LiveView.Utils.maybe_call_update!/3
      (elixir 1.18.3) lib/enum.ex:1714: Enum."-map/2-lists^map/1-1-"/2
      (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:694: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6
      (telemetry 1.3.0) /Users/albin/projects/a/ash_events_test/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3
      (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:689: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6
      (stdlib 6.2.2) maps.erl:860: :maps.fold_1/4
      (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:648: Phoenix.LiveView.Diff.render_pending_components/6
      (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:143: Phoenix.LiveView.Diff.render/3
      (phoenix_live_view 1.0.12) lib/phoenix_live_view/static.ex:289: Phoenix.LiveView.Static.to_rendered_content_tag/4
      (phoenix_live_view 1.0.12) lib/phoenix_live_view/static.ex:171: Phoenix.LiveView.Static.do_render/4
        (ash_authentication 4.8.7) lib/ash_authentication/info.ex:68: AshAuthentication.Info.strategy_for_action!/2
        (ash_authentication 4.8.7) lib/ash_authentication/strategies/magic_link/sign_in_change.ex:19: AshAuthentication.Strategy.MagicLink.SignInChange.change/3
        (ash 3.5.12) lib/ash/changeset/changeset.ex:2841: Ash.Changeset.run_change_or_validation/6
        (ash 3.5.12) lib/ash/changeset/changeset.ex:2700: anonymous fn/6 in Ash.Changeset.run_action_changes/6
        (elixir 1.18.3) lib/enum.ex:2546: Enum."-reduce/3-lists^foldl/2-0-"/3
        (ash 3.5.12) lib/ash/changeset/changeset.ex:2696: Ash.Changeset.run_action_changes/6
        (ash 3.5.12) lib/ash/changeset/changeset.ex:2167: Ash.Changeset.do_for_action/4
        (ash_phoenix 2.3.2) lib/ash_phoenix/form/form.ex:603: AshPhoenix.Form.for_create/3
        (ash_admin 0.13.5) lib/ash_admin/components/resource/form.ex:2203: AshAdmin.Components.Resource.Form.assign_form/1
        (ash_admin 0.13.5) lib/ash_admin/components/resource/form.ex:38: AshAdmin.Components.Resource.Form.update/2
        (phoenix_live_view 1.0.12) lib/phoenix_live_view/utils.ex:492: Phoenix.LiveView.Utils.maybe_call_update!/3
        (elixir 1.18.3) lib/enum.ex:1714: Enum."-map/2-lists^map/1-1-"/2
        (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:694: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6
        (telemetry 1.3.0) /Users/albin/projects/a/ash_events_test/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3
        (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:689: anonymous fn/4 in Phoenix.LiveView.Diff.render_pending_components/6
        (stdlib 6.2.2) maps.erl:860: :maps.fold_1/4
        (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:648: Phoenix.LiveView.Diff.render_pending_components/6
        (phoenix_live_view 1.0.12) lib/phoenix_live_view/diff.ex:143: Phoenix.LiveView.Diff.render/3
        (phoenix_live_view 1.0.12) lib/phoenix_live_view/static.ex:289: Phoenix.LiveView.Static.to_rendered_content_tag/4
        (phoenix_live_view 1.0.12) lib/phoenix_live_view/static.ex:171: Phoenix.LiveView.Static.do_render/4
    

Code:

`lib/ash_authentication/info.ex`

    63       case strategy_for_action(dsl_or_resource, action_name) do
    64         {:ok, value} -&gt;
    65           value
    66   
    67         :error -&gt;
    68>          raise &quot;No strategy action named `#{inspect(action_name)}` found on resource `#{inspect(dsl_or_resource)}`&quot;
    69       end
    70     end
    71   
    72     @doc &quot;&quot;&quot;
    73     Find the underlying strategy that required a change/preparation to be used.
    
`lib/ash_authentication/strategies/magic_link/sign_in_change.ex`

    14       subject_name =
    15         changeset.resource
    16         |&gt; Info.authentication_subject_name!()
    17         |&gt; to_string()
    18   
    19>      strategy = Info.strategy_for_action!(changeset.resource, changeset.action.name)
    20   
    21       with token when is_binary(token) &lt;-
    22              Changeset.get_argument(changeset, strategy.token_param_name),
    23            {:ok, %{&quot;act&quot; =&gt; token_action, &quot;sub&quot; =&gt; subject, &quot;identity&quot; =&gt; identity}, _} &lt;-
    24              Jwt.verify(token, changeset.resource, [], context),
    
`lib/ash/changeset/changeset.ex`

    2836                       args: changeset.arguments,
    2837                       context: changeset.context,
    2838                       changeset: changeset
    2839                     )
    2840   
    2841>                  module.change(
    2842                     changeset,
    2843                     opts,
    2844                     struct(Ash.Resource.Change.Context, context)
    2845                   )
    2846                 end
    
`lib/ash/changeset/changeset.ex`

    2695       changes
    2696       |&gt; Enum.reduce(changeset, fn {location, change_or_validation}, changeset -&gt;
    2697         try do
    2698           context = %{context | tenant: changeset.tenant}
    2699   
    2700>          run_change_or_validation(
    2701             change_or_validation,
    2702             changeset,
    2703             context,
    2704             tracer,
    2705             metadata,
    
`lib/enum.ex`

    No code available.

`lib/ash/changeset/changeset.ex`

    2691         authorize?: authorize? || false,
    2692         tracer: tracer
    2693       }
    2694   
    2695       changes
    2696>      |&gt; Enum.reduce(changeset, fn {location, change_or_validation}, changeset -&gt;
    2697         try do
    2698           context = %{context | tenant: changeset.tenant}
    2699   
    2700           run_change_or_validation(
    2701             change_or_validation,
    
`lib/ash/changeset/changeset.ex`

    2162   
    2163                 changeset =
    2164                   changeset
    2165                   |&gt; prepare_changeset_for_action(action, opts)
    2166                   |&gt; handle_params(action, params, opts)
    2167>                  |&gt; run_action_changes(
    2168                     action,
    2169                     opts[:actor],
    2170                     opts[:authorize?],
    2171                     opts[:tracer],
    2172                     metadata
    
`lib/ash_phoenix/form/form.ex`

    598         |&gt; Ash.Changeset.new()
    599         |&gt; prepare_source.()
    600         |&gt; set_accessing_from(opts)
    601   
    602       source =
    603>        Ash.Changeset.for_create(
    604           source,
    605           action,
    606           params,
    607           allow_all_keys_to_be_skipped(changeset_opts, params)
    608         )
    
`lib/ash_admin/components/resource/form.ex`

    2198   
    2199       form =
    2200         case socket.assigns.action.type do
    2201           :create -&gt;
    2202             socket.assigns.resource
    2203>            |&gt; AshPhoenix.Form.for_create(socket.assigns.action.name,
    2204               domain: socket.assigns.domain,
    2205               actor: socket.assigns[:actor],
    2206               authorize?: socket.assigns[:authorizing],
    2207               forms: auto_forms,
    2208               transform_errors: transform_errors,
    
`lib/ash_admin/components/resource/form.ex`

    33     def update(assigns, socket) do
    34       {:ok,
    35        socket
    36        |&gt; assign(assigns)
    37        |&gt; assign(:typeahead_options, [])
    38>       |&gt; assign_form()
    39        |&gt; assign(:initialized, true)}
    40     end
    41   
    42     def render(assigns) do
    43       ~H&quot;&quot;&quot;
    
`lib/phoenix_live_view/utils.ex`

    487                       &quot;of the same length as the input list, got: #{inspect(other)}&quot;
    488           end
    489   
    490         function_exported?(component, :update, 2) -&gt;
    491           socket =
    492>            case component.update(assigns, socket) do
    493               {:ok, %Socket{} = socket} -&gt;
    494                 socket
    495   
    496               other -&gt;
    497                 raise ArgumentError, &quot;&quot;&quot;
    
`lib/enum.ex`

    No code available.

`lib/phoenix_live_view/diff.ex`

    689             :telemetry.span([:phoenix, :live_component, :update], telemetry_metadata, fn -&gt;
    690               sockets =
    691                 if update_many? do
    692                   component.update_many(assigns_sockets)
    693                 else
    694>                  Enum.map(assigns_sockets, fn {assigns, socket} -&gt;
    695                     Utils.maybe_call_update!(socket, component, assigns)
    696                   end)
    697                 end
    698   
    699               {sockets, Map.put(telemetry_metadata, :sockets, sockets)}
    
`/Users/albin/projects/a/ash_events_test/deps/telemetry/src/telemetry.erl`

    319           EventPrefix ++ [start],
    320           #{monotonic_time =&gt; StartTime, system_time =&gt; erlang:system_time()},
    321           merge_ctx(StartMetadata, DefaultCtx)
    322       ),
    323   
    324>      try SpanFunction() of
    325         {Result, StopMetadata} -&gt;
    326             StopTime = erlang:monotonic_time(),
    327             execute(
    328                 EventPrefix ++ [stop],
    329                 #{duration =&gt; StopTime - StartTime, monotonic_time =&gt; StopTime},
    
`lib/phoenix_live_view/diff.ex`

    684             component: component,
    685             assigns_sockets: assigns_sockets
    686           }
    687   
    688           sockets =
    689>            :telemetry.span([:phoenix, :live_component, :update], telemetry_metadata, fn -&gt;
    690               sockets =
    691                 if update_many? do
    692                   component.update_many(assigns_sockets)
    693                 else
    694                   Enum.map(assigns_sockets, fn {assigns, socket} -&gt;
    
`maps.erl`

    No code available.

`lib/phoenix_live_view/diff.ex`

    643   
    644     defp render_pending_components(socket, pending, seen_ids, cids, diffs, components) do
    645       acc = {{%{}, diffs, components}, seen_ids}
    646   
    647       {{pending, diffs, components}, seen_ids} =
    648>        Enum.reduce(pending, acc, fn {component, entries}, acc -&gt;
    649           {{pending, diffs, components}, seen_ids} = acc
    650           update_many? = function_exported?(component, :update_many, 1)
    651           entries = maybe_preload_components(component, Enum.reverse(entries))
    652   
    653           {assigns_sockets, metadata, components, seen_ids} =
    
`lib/phoenix_live_view/diff.ex`

    138       # cid_to_component is used by maybe_reuse_static and it must be a copy before changes.
    139       # However, given traverse does not change cid_to_component, we can read it now.
    140       {cid_to_component, _, _} = components
    141   
    142       {cdiffs, components} =
    143>        render_pending_components(socket, pending, cid_to_component, %{}, components)
    144   
    145       socket = %{socket | fingerprints: prints}
    146       diff = maybe_put_title(diff, socket)
    147       {diff, cdiffs} = extract_events({diff, cdiffs})
    148       {socket, maybe_put_cdiffs(diff, cdiffs), components}
    
`lib/phoenix_live_view/static.ex`

    284       content_tag(tag, attrs, &quot;&quot;)
    285     end
    286   
    287     defp to_rendered_content_tag(socket, tag, view, attrs) do
    288       rendered = Phoenix.LiveView.Renderer.to_rendered(socket, view)
    289>      {_, diff, _} = Diff.render(socket, rendered, Diff.new_components())
    290       content_tag(tag, attrs, Diff.to_iodata(diff))
    291     end
    292   
    293     defp content_tag(tag, attrs, content) do
    294       tag = to_string(tag)
    
`lib/phoenix_live_view/static.ex`

    166             {:data, data_attrs}
    167             | extended_attrs
    168           ]
    169   
    170           try do
    171>            {:ok, to_rendered_content_tag(socket, tag, view, attrs), socket.assigns}
    172           catch
    173             :throw, {:phoenix, :child_redirect, redirected, flash} -&gt;
    174               {:stop, Utils.replace_flash(%{socket | redirected: redirected}, flash)}
    175           end
    176   
    

## Connection details

### Params

    %{"action" => "sign_in_with_magic_link_ash_events_orig_impl", "action_type" => "create", "domain" => "Accounts", "resource" => "User", "route" => [], "table" => ""}

### Request info

  * URI: http://localhost:4000/admin
  * Query string: domain=Accounts&resource=User&action_type=create&action=sign_in_with_magic_link_ash_events_orig_impl&table=

### Headers
  
  * accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
  * accept-encoding: gzip, deflate, br, zstd
  * accept-language: en-US,en;q=0.9
  * connection: keep-alive
  * cookie: _live_debugger=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYeXBSdEd2aUMtb2tYOU5kUnZKbmpOVWk4.xZ-k5l5_uEm3xXRlAJcIe5b313AO9UaFCDG9imWuz5Y; _ash_events_test_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYdHFPcjFtTDdWaG50RzFOVHZQbVNmeThK.IbXNtjE5uT2KjusKsfMnWHHMPFEeAtbWKlhSeMIXy1k
  * host: localhost:4000
  * referer: http://localhost:4000/admin?domain=Accounts&resource=User
  * sec-ch-ua: "Not.A/Brand";v="99", "Chromium";v="136"
  * sec-ch-ua-mobile: ?0
  * sec-ch-ua-platform: "macOS"
  * 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 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36

### Session

    %{"_csrf_token" => "tqOr1mL7VhntG1NTvPmSfy8J"}
zachdaniel

zachdaniel

Creator of Ash

froze for 5-10 seconds :thinking: wacky. That sounds like some kind of ash_admin error handling bug?

But this appears to be something we essentially just didn’t consider which is that ash_authentication depends on the name of the action lining up to do what it does.

I think we need to make two changes:

  1. pass context from the parent to the child
  2. you may need to set into your actions change set_context(%{strategy_name: :password}) so that ash_authentication picks it up from the context

AshEvents is pretty young, so there may be interactions like this that need to be considered.

#1 is relatively straightforward to do if you’d like to try your hand at a PR. In the action wrappers:

defmodule AshEvents.CreateActionWrapper do
  @moduledoc """
  Wrapper for create actions that enables event tracking.
  """
  use Ash.Resource.ManualCreate
  alias AshEvents.Helpers

  def create(changeset, module_opts, ctx) do
    opts =
      ctx
      |> Ash.Context.to_opts()
      |> Keyword.put(:return_notifications?, ctx.return_notifications? || false)

    params = AshEvents.Events.ActionWrapperHelpers.build_params(changeset, module_opts)

    AshEvents.Events.ActionWrapperHelpers.create_event!(changeset, params, module_opts, opts)

    original_action_name = Helpers.build_original_action_name(module_opts[:action])

    changeset.resource
    |> Ash.Changeset.new() # <- add this line
    |> Ash.Changeset.set_context(changeset.context) # <- and this one
    |> Ash.Changeset.for_create(original_action_name, params, opts)
    |> Ash.create(opts)
  end
end

albin

albin OP

Here’s a draft PR I created. Please review.
https://github.com/ash-project/ash_events/pull/20

zachdaniel

zachdaniel

Creator of Ash

LGTM, will let @Torkan review. It is a draft, would you prefer it not be merged? Does that PR resolve your issue?

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews