LiveView - (FunctionClauseError) no function clause matching with event_handler without any event to handle

Hi,

This seems to be strange for me, but without any updates of libraries or even elixir part of app doesnt work like before.

I have got few views which show list of products, categories, brands etc. Problem seems to be repeated everytime being in show window. Instead of adding to cart or refuse adding to cart it invokes error with event_handler from index window. I will paste just code from ex and html for one of those, because code is similar everywhere and problem seems to happens everytime (sometimes it works if I open VSCode and add IO.inspect() on handler an save it (LOL), but after few tries it crashes again)

category_index.ex

@impl true
  def mount(_params, %{"user_token" => user_token}, socket) do
    user = Accounts.get_user_by_session_token(user_token)

    {:ok,
      socket
      |> assign(:current_user, user)
      |> assign(:categories, Catalog.list_categories())}
  end

  def mount(_params, _session, socket) do
    {:ok, assign(socket, :categories, Catalog.list_categories())}
  end

  @impl true
  def handle_params(params, _url, socket) do
    {:noreply, apply_action(socket, socket.assigns.live_action, params)}
  end

  defp apply_action(socket, :show, %{"id" => id}) do
    socket
      |> assign(:page_title, "Show Category")
      |> assign(:category, Catalog.get_category!(id))
      |> assign(:products, Catalog.get_available_products_by_category_id(id))
  end

  defp apply_action(socket, :index, _params) do
    socket
    |> assign(:page_title, "Listing Categories")
    |> assign(:category, nil)
  end
end

category_index.html.heex

<div class="bg-white mx-auto h-screen justify-items-center">
<section class="mx-auto max-w-screen-lg justify-items-center mt-10 mb-5">
  <img
    alt="category image"
    src={ ~s[/images/main-site-photo.jpg]}>
  </section>
  <div class="mx-auto mb-10">
    <p class="text-center text-blue-500 md:text-2xl sm:text-xl">The best equipment for your office</p>
  </div>
  <div class="grid grid-cols-1 md:grid-cols-3 mx-auto justify-center max-w-7xl">
    <%= for category <- @categories do %>
      <%= live_redirect to: Routes.category_show_path(@socket, :show, category.id) do %>
        <div class="flex flex-col content-between justify-center mx-auto my-10 " id={"category-#{category.id}"}>
          <div class="self-center w-64 h-64">
            <img
              alt="category image" width="250" height="250"
              src={ Routes.static_path(@socket, category.image_upload || ~s[/images/default-thumbnail.jpg])} >
          </div>
          <p class="text-center text-blue-500 md:text-2xl sm:text-xl mt-5"><%= category.name %></p>
        </div>
      <% end %>
    <% end %>
  </div>
</div>

As Its written - this window contains only redirections to specific categories and list of products in it. Zero event_handlers, I dont even know if I need handle_params here…

and

category_show.ex

@impl true

  def mount(_params, %{"user_token" => user_token}, socket) do
    user = Accounts.get_user_by_session_token(user_token)

    {:ok,
      socket
      |> assign(:current_user, user)
      |> assign(:cart, ShoppingCart.get_cart_by_user_id(user.id))
      |> assign(:cart_items, %CartItem{})}
  end

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  @impl true
  def handle_event("add_to_cart", %{"product" => product_id, "quantity" => quantity}, socket) do
    IO.inspect(product_id)
    IO.inspect(quantity)
    case socket.assigns[:current_user] do
      %Eshopy.Accounts.User{role: :user} ->
        create_and_add_item(product_id, quantity, socket)

      _ ->
      {:noreply,
        socket
        |> put_flash(:info, "You must be logged in")}
    end
  end

  @impl true
  def handle_params(%{"id" => id}, _, socket) do
    {:noreply,
      socket
      |> assign(:page_title, "Show Category")
      |> assign(:category, Catalog.get_category!(id))
      |> assign(:products, Catalog.get_available_products_by_category_id(id))}
  end

  defp create_and_add_item(product_id, quantity, socket) do
    product = Catalog.get_product!(product_id)
    quantity = String.to_integer(quantity)

    socket =
      case ShoppingCart.get_cart_by_user_id(socket.assigns.current_user.id) do
        %Cart{} = cart ->
          add_item_to_shopping_cart(socket, cart, product, quantity)

        nil ->
          {:ok, %Cart{} = cart} = ShoppingCart.create_cart(socket.assigns.current_user)
          add_item_to_shopping_cart(socket, cart, product, quantity)
      end

    {:noreply, socket}
  end

  defp add_item_to_shopping_cart(socket, cart, product, quantity) do
    case ShoppingCart.add_item_to_cart(cart, product, quantity) do
          {:ok, _item} ->
            socket
            |> put_flash(:info, "Item added to shopping cart")

          {:error, _changeset} ->
            socket
            |> put_flash(:info, "Error with adding item")
    end
  end
end

category_show.html.heex

<div>
    <p class="text-center text-blue-500 md:text-2xl text-xl"><strong><%= @category.name %></strong></p>
    <div class="flex flex-wrap mx-auto justify-center max-w-7xl">
        <%= for product <- @products do %>
          <div class="flex flex-col mx-auto my-5">
            <%= live_redirect to: Routes.product_show_path(@socket, :show, product.id) do %>
              <div class="grid grid-cols-1 content-center justify-center mx-auto" id={"product-#{product.id}"}>
                <div class="self-center w-64 h-64">
                  <img
                    alt="product image" width="250" height="250"
                    src={ product.image_upload } >
                </div>
                    <p class="text-center text-blue-500 md:text-2xl sm:text-xl mt-5"><strong><%= product.name %></strong></p>
                    <p class="text-center text-blue-500 md:text-xl sm:text-xl"><%= Catalog.get_category!(product.category_id).name %></p>
                    <p class="text-center text-blue-500 md:text-2xl sm:text-xl"><em><%= product.unit_price %>$</em></p>
              </div>
            <% end %>
            <button class="bg-blue-400 text-white font-[Poppins] duration-500 px-6 py-2 md:my-0 hover:bg-blue-600 rounded" phx-click="add_to_cart" phx-value-product={product.id} phx-value-quantity={1}>Add to cart</button>
          </div>
        <% end %>
    </div>
</div>

Being in show window I click add_to_cart. It doesnt matter if I am logged in or not it crashes and redirects me to category_index page (even if i receive flash that Product has been added to cart :D) and terminal becomes red with error like that:

I paste all of it, maybe someone catches things that i can not.

[error] GenServer #PID<0.1152.0> terminating
** (UndefinedFunctionError) function EshopyWeb.BrandLive.Index.handle_event/3 is undefined or private
    (eshopy 0.1.0) EshopyWeb.BrandLive.Index.handle_event("add_to_cart", %{"product" => "5", "quantity" => "1", "value" => ""}, #Phoenix.LiveView.Socket<assigns: %{__changed__: %{}, brand: nil, brands: [%Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 1, image_upload: "/images/live_view_upload-1675197775-472722086641-2", inserted_at: ~N[2023-01-31 20:42:59], name: "Huawei", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:42:59]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 2, image_upload: "/images/live_view_upload-1675197790-688965978619-1", inserted_at: ~N[2023-01-31 20:43:11], name: "Apple", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:11]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 3, image_upload: "/images/live_view_upload-1675197802-989508123695-6", inserted_at: ~N[2023-01-31 20:43:24], name: "Logitech", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:24]}], current_user: #Eshopy.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, confirmed_at: nil, customer: #Ecto.Association.NotLoaded<association :customer is not loaded>, email: "admin@pl", id: 1, inserted_at: ~N[2023-01-31 20:37:48], role: :user, updated_at: ~N[2023-02-08 16:52:14], ...>, flash: %{}, live_action: :index, page_title: "Listing Brands"}, endpoint: EshopyWeb.Endpoint, id: "phx-F0SISDHsRoJ5PgQJ", parent_pid: nil, root_pid: #PID<0.1152.0>, router: EshopyWeb.Router, transport_pid: #PID<0.1140.0>, view: EshopyWeb.BrandLive.Index, ...>)
    (phoenix_live_view 0.17.12) lib/phoenix_live_view/channel.ex:382: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
    (telemetry 1.1.0) /home/mateusz/Pulpit/eshopy/deps/telemetry/src/telemetry.erl:320: :telemetry.span/3
    (phoenix_live_view 0.17.12) lib/phoenix_live_view/channel.ex:216: Phoenix.LiveView.Channel.handle_info/2
    (stdlib 4.0.1) gen_server.erl:1120: :gen_server.try_dispatch/4
    (stdlib 4.0.1) gen_server.erl:1197: :gen_server.handle_msg/6
    (stdlib 4.0.1) proc_lib.erl:250: :proc_lib.wake_up/3
Last message: %Phoenix.Socket.Message{event: "event", join_ref: "7", payload: %{"event" => "add_to_cart", "type" => "click", "value" => %{"product" => "5", "quantity" => "1", "value" => ""}}, ref: "20", topic: "lv:phx-F0SISDHsRoJ5PgQJ"}
State: %{components: {%{}, %{}, 1}, join_ref: "7", serializer: Phoenix.Socket.V2.JSONSerializer, socket: #Phoenix.LiveView.Socket<assigns: %{__changed__: %{}, brand: nil, brands: [%Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 1, image_upload: "/images/live_view_upload-1675197775-472722086641-2", inserted_at: ~N[2023-01-31 20:42:59], name: "Huawei", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:42:59]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 2, image_upload: "/images/live_view_upload-1675197790-688965978619-1", inserted_at: ~N[2023-01-31 20:43:11], name: "Apple", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:11]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 3, image_upload: "/images/live_view_upload-1675197802-989508123695-6", inserted_at: ~N[2023-01-31 20:43:24], name: "Logitech", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:24]}], current_user: #Eshopy.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, confirmed_at: nil, customer: #Ecto.Association.NotLoaded<association :customer is not loaded>, email: "admin@pl", id: 1, inserted_at: ~N[2023-01-31 20:37:48], role: :user, updated_at: ~N[2023-02-08 16:52:14], ...>, flash: %{}, live_action: :index, page_title: "Listing Brands"}, endpoint: EshopyWeb.Endpoint, id: "phx-F0SISDHsRoJ5PgQJ", parent_pid: nil, root_pid: #PID<0.1152.0>, router: EshopyWeb.Router, transport_pid: #PID<0.1140.0>, view: EshopyWeb.BrandLive.Index, ...>, topic: "lv:phx-F0SISDHsRoJ5PgQJ", upload_names: %{}, upload_pids: %{}}

To make it works I need to copy/paste all handlers to index.ex what sounds like a bull***t.
Recently I started using socket and channels to track users - after that feature it started to showing me that error. Is is possible that its the reason? Logically it shouldnt be…

I tried to play with it.

I added function to category_index.ex:

@impl true
  def handle_event("add_to_cart", _, socket) do
    {:noreply, socket}
  end

And now category_show is working well. I add product to cart, and only flash appears. Being logged out flash appears, but i cant add to cart anything. Like it should work.

Otherwise without putting “empty” handler other views dont work. In brand_show view after clicking button I got:

Flash: "Item added to shopiing cart. (And it really appears in cart :D)

Redirects to: brand_index view (it should never happen).

Error:

[error] GenServer #PID<0.3285.0> terminating
** (UndefinedFunctionError) function EshopyWeb.BrandLive.Index.handle_event/3 is undefined or private
    (eshopy 0.1.0) EshopyWeb.BrandLive.Index.handle_event("add_to_cart", %{"product" => "5", "quantity" => "1", "value" => ""}, #Phoenix.LiveView.Socket<assigns: %{__changed__: %{}, brand: nil, brands: [%Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 1, image_upload: "/images/live_view_upload-1675197775-472722086641-2", inserted_at: ~N[2023-01-31 20:42:59], name: "Huawei", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:42:59]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 2, image_upload: "/images/live_view_upload-1675197790-688965978619-1", inserted_at: ~N[2023-01-31 20:43:11], name: "Apple", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:11]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 3, image_upload: "/images/live_view_upload-1675197802-989508123695-6", inserted_at: ~N[2023-01-31 20:43:24], name: "Logitech", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:24]}], current_user: #Eshopy.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, confirmed_at: nil, customer: #Ecto.Association.NotLoaded<association :customer is not loaded>, email: "admin@pl", id: 1, inserted_at: ~N[2023-01-31 20:37:48], role: :user, updated_at: ~N[2023-02-08 16:52:14], ...>, flash: %{}, live_action: :index, page_title: "Listing Brands"}, endpoint: EshopyWeb.Endpoint, id: "phx-F0SskhP04L3JtRGC", parent_pid: nil, root_pid: #PID<0.3285.0>, router: EshopyWeb.Router, transport_pid: #PID<0.3267.0>, view: EshopyWeb.BrandLive.Index, ...>)
    (phoenix_live_view 0.17.12) lib/phoenix_live_view/channel.ex:382: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
    (telemetry 1.1.0) /home/mateusz/Pulpit/eshopy/deps/telemetry/src/telemetry.erl:320: :telemetry.span/3
    (phoenix_live_view 0.17.12) lib/phoenix_live_view/channel.ex:216: Phoenix.LiveView.Channel.handle_info/2
    (stdlib 4.0.1) gen_server.erl:1120: :gen_server.try_dispatch/4
    (stdlib 4.0.1) gen_server.erl:1197: :gen_server.handle_msg/6
    (stdlib 4.0.1) proc_lib.erl:250: :proc_lib.wake_up/3
Last message: %Phoenix.Socket.Message{event: "event", join_ref: "7", payload: %{"event" => "add_to_cart", "type" => "click", "value" => %{"product" => "5", "quantity" => "1", "value" => ""}}, ref: "9", topic: "lv:phx-F0SskhP04L3JtRGC"}
State: %{components: {%{}, %{}, 1}, join_ref: "7", serializer: Phoenix.Socket.V2.JSONSerializer, socket: #Phoenix.LiveView.Socket<assigns: %{__changed__: %{}, brand: nil, brands: [%Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 1, image_upload: "/images/live_view_upload-1675197775-472722086641-2", inserted_at: ~N[2023-01-31 20:42:59], name: "Huawei", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:42:59]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 2, image_upload: "/images/live_view_upload-1675197790-688965978619-1", inserted_at: ~N[2023-01-31 20:43:11], name: "Apple", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:11]}, %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 3, image_upload: "/images/live_view_upload-1675197802-989508123695-6", inserted_at: ~N[2023-01-31 20:43:24], name: "Logitech", products: #Ecto.Association.NotLoaded<association :products is not loaded>, updated_at: ~N[2023-01-31 20:43:24]}], current_user: #Eshopy.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, confirmed_at: nil, customer: #Ecto.Association.NotLoaded<association :customer is not loaded>, email: "admin@pl", id: 1, inserted_at: ~N[2023-01-31 20:37:48], role: :user, updated_at: ~N[2023-02-08 16:52:14], ...>, flash: %{}, live_action: :index, page_title: "Listing Brands"}, endpoint: EshopyWeb.Endpoint, id: "phx-F0SskhP04L3JtRGC", parent_pid: nil, root_pid: #PID<0.3285.0>, router: EshopyWeb.Router, transport_pid: #PID<0.3267.0>, view: EshopyWeb.BrandLive.Index, ...>, topic: "lv:phx-F0SskhP04L3JtRGC", upload_names: %{}, upload_pids: %{}}

It looks really strange, few days back everything worked well.

2 Likes

I updated Elixir, Phoenix and LiveView to newest versions. Refactored all live_patch, live_redirect etc. according to documentation. Nothing changes in this case, even in admin panel I have change status function for products, but clicking it (for now I dont even care, that browser asks me 5 times if I am sure…) provides to error in another liveview (but still changes what I wanted) xD.

Whats more, everytime I try to delete some product etc shows Ecto.StaleEntryError - but still deletes what I wanted… Is bizarre, because I have never got those errors. Which are not described well in documentation (that error is not desribed at all…)

Why when I click event button on products view it invokes event twice - products and admin dashboard…

SELECT c0."id", c0."name", c0."image_upload", c0."inserted_at", c0."updated_at" FROM "categories" AS c0 []
↳ EshopyWeb.AdminLive.Products.mount/3, at: lib/eshopy_web/live/admin_live/products/products.ex:26
[debug] Replied in 11ms
[debug] HANDLE PARAMS
  View: EshopyWeb.AdminLive.Products
  Parameters: %{}
[debug] Replied in 33µs
[debug] HANDLE EVENT
  View: EshopyWeb.AdminLive.Products
  Event: "change"
  Parameters: %{"id" => "5", "value" => ""}
[debug] HANDLE EVENT
  View: EshopyWeb.AdminLive.Dashboard
  Event: "change"
  Parameters: %{"id" => "5", "value" => ""}
[debug] QUERY OK source="products" db=1.9ms queue=0.3ms idle=258.8ms
SELECT p0."id", p0."description", p0."name", p0."sku", p0."unit_price", p0."image_upload", p0."available", p0."brand_id", p0."category_id", p0."inserted_at", p0."updated_at" FROM "products" AS p0 WHERE (p0."id" = $1) [5]
↳ Eshopy.Catalog.get_product!/1, at: lib/eshopy/catalog.ex:57
[debug] QUERY OK source="brands" db=0.3ms queue=0.3ms idle=261.4ms
SELECT b0."id", b0."name", b0."image_upload", b0."inserted_at", b0."updated_at", b0."id" FROM "brands" AS b0 WHERE (b0."id" = $1) [1]
↳ EshopyWeb.AdminLive.Products.handle_event/3, at: lib/eshopy_web/live/admin_live/products/products.ex:39
[debug] QUERY OK source="categories" db=0.4ms queue=0.5ms idle=261.4ms
SELECT c0."id", c0."name", c0."image_upload", c0."inserted_at", c0."updated_at", c0."id" FROM "categories" AS c0 WHERE (c0."id" = $1) [3]
↳ EshopyWeb.AdminLive.Products.handle_event/3, at: lib/eshopy_web/live/admin_live/products/products.ex:39
[debug] QUERY OK db=3.4ms queue=0.5ms idle=275.3ms
UPDATE "products" SET "available" = $1, "updated_at" = $2 WHERE "id" = $3 [false, ~N[2023-02-19 11:27:33], 5]
↳ EshopyWeb.AdminLive.Products.handle_event/3, at: lib/eshopy_web/live/admin_live/products/products.ex:40
[debug] QUERY OK source="products" db=0.6ms queue=0.1ms idle=282.2ms
SELECT p0."id", p0."description", p0."name", p0."sku", p0."unit_price", p0."image_upload", p0."available", p0."brand_id", p0."category_id", p0."inserted_at", p0."updated_at" FROM "products" AS p0 []
↳ Eshopy.Catalog.list_products/0, at: lib/eshopy/catalog.ex:23
[debug] QUERY OK source="categories" db=0.2ms idle=283.2ms
SELECT c0."id", c0."name", c0."image_upload", c0."inserted_at", c0."updated_at", c0."id" FROM "categories" AS c0 WHERE (c0."id" = ANY($1)) [[1, 3, 4]]
↳ EshopyWeb.AdminLive.Products.handle_event/3, at: lib/eshopy_web/live/admin_live/products/products.ex:45
[debug] QUERY OK source="brands" db=0.5ms idle=283.3ms
SELECT b0."id", b0."name", b0."image_upload", b0."inserted_at", b0."updated_at", b0."id" FROM "brands" AS b0 WHERE (b0."id" = ANY($1)) [[2, 3, 1]]
↳ EshopyWeb.AdminLive.Products.handle_event/3, at: lib/eshopy_web/live/admin_live/products/products.ex:45
[debug] QUERY OK source="brands" db=0.5ms idle=283.9ms
SELECT b0."id", b0."name", b0."image_upload", b0."inserted_at", b0."updated_at" FROM "brands" AS b0 []
↳ EshopyWeb.AdminLive.Products.handle_event/3, at: lib/eshopy_web/live/admin_live/products/products.ex:46
[debug] QUERY OK source="categories" db=0.4ms idle=284.5ms
SELECT c0."id", c0."name", c0."image_upload", c0."inserted_at", c0."updated_at" FROM "categories" AS c0 []
↳ EshopyWeb.AdminLive.Products.handle_event/3, at: lib/eshopy_web/live/admin_live/products/products.ex:47
[debug] Replied in 26ms
[error] GenServer #PID<0.729.0> terminating
** (UndefinedFunctionError) function EshopyWeb.AdminLive.Dashboard.handle_event/3 is undefined or private
    (eshopy 0.1.0) EshopyWeb.AdminLive.Dashboard.handle_event("change", %{"id" => "5", "value" => ""}, #Phoenix.LiveView.Socket<id: "phx-F0U2NjBDCpA14QBG", endpoint: EshopyWeb.Endpoint, view: EshopyWeb.AdminLive.Dashboard, parent_pid: nil, root_pid: #PID<0.729.0>, router: EshopyWeb.Router, assigns: %{__changed__: %{}, current_user: #Eshopy.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 3, email: "szef@pl", confirmed_at: nil, role: :admin, customer: #Ecto.Association.NotLoaded<association :customer is not loaded>, inserted_at: ~N[2023-02-03 06:29:12], updated_at: ~N[2023-02-08 16:51:39], ...>, flash: %{}, live_action: :dashboard}, transport_pid: #PID<0.724.0>, ...>)
    (phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:396: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
    (telemetry 1.2.1) /home/mateusz/Pulpit/eshopy/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
    (phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:216: Phoenix.LiveView.Channel.handle_info/2
    (stdlib 4.2) gen_server.erl:1123: :gen_server.try_dispatch/4
    (stdlib 4.2) gen_server.erl:1200: :gen_server.handle_msg/6
    (stdlib 4.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F0U2NjBDCpA14QBG", event: "event", payload: %{"event" => "change", "type" => "click", "value" => %{"id" => "5", "value" => ""}}, ref: "8", join_ref: "4"}
State: %{components: {%{}, %{}, 1}, join_ref: "4", serializer: Phoenix.Socket.V2.JSONSerializer, socket: #Phoenix.LiveView.Socket<id: "phx-F0U2NjBDCpA14QBG", endpoint: EshopyWeb.Endpoint, view: EshopyWeb.AdminLive.Dashboard, parent_pid: nil, root_pid: #PID<0.729.0>, router: EshopyWeb.Router, assigns: %{__changed__: %{}, current_user: #Eshopy.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 3, email: "szef@pl", confirmed_at: nil, role: :admin, customer: #Ecto.Association.NotLoaded<association :customer is not loaded>, inserted_at: ~N[2023-02-03 06:29:12], updated_at: ~N[2023-02-08 16:51:39], ...>, flash: %{}, live_action: :dashboard}, transport_pid: #PID<0.724.0>, ...>, topic: "lv:phx-F0U2NjBDCpA14QBG", upload_names: %{}, upload_pids: %{}}
[debug] MOUNT EshopyWeb.AdminLive.Dashboard
  Parameters: %{}
  Session: %{"_csrf_token" => "pKlEvl8Qf5uonSBPGX42f2lA", "live_socket_id" => "users_sessions:AHVuCUh_UEPfl4BF_-9702JQflP9YYQIY32M42Py5CA=", "user_token" => <<0, 117, 110, 9, 72, 127, 80, 67, 223, 151, 128, 69, 255, 239, 123, 211, 98, 80, 126, 83, 253, 97, 132, 8, 99, 125, 140, 227, 99, 242, 228, 32>>}
[debug] QUERY OK source="users_tokens" db=0.5ms idle=1300.4ms
SELECT u1."id", u1."email", u1."hashed_password", u1."confirmed_at", u1."role", u1."inserted_at", u1."updated_at" FROM "users_tokens" AS u0 INNER JOIN "users" AS u1 ON u1."id" = u0."user_id" WHERE ((u0."token" = $1) AND (u0."context" = $2)) AND (u0."inserted_at" > $3::timestamp + (-(60)::numeric * interval '1 day')) [<<0, 117, 110, 9, 72, 127, 80, 67, 223, 151, 128, 69, 255, 239, 123, 211, 98, 80, 126, 83, 253, 97, 132, 8, 99, 125, 140, 227, 99, 242, 228, 32>>, "session", ~U[2023-02-19 11:27:34.698229Z]]
↳ EshopyWeb.AdminLive.Dashboard.mount/3, at: lib/eshopy_web/live/admin_live/dashboard.ex:9

And here trace of this error that started to appear few days ago from nowhere:

[debug] Replied in 802µs
[debug] HANDLE EVENT
  View: EshopyWeb.CartLive.Show
  Event: "clear_cart"
  Parameters: %{"value" => ""}
[debug] HANDLE EVENT
  View: EshopyWeb.CartLive.Show
  Event: "clear_cart"
  Parameters: %{"value" => ""}
[debug] QUERY OK db=2.8ms queue=0.2ms idle=1523.1ms
DELETE FROM "carts" WHERE "id" = $1 [23]
↳ EshopyWeb.CartLive.Show.handle_event/3, at: lib/eshopy_web/live/cart_live/show.ex:55
[debug] QUERY OK db=2.7ms queue=0.1ms idle=1523.1ms
DELETE FROM "carts" WHERE "id" = $1 [23]
↳ EshopyWeb.CartLive.Show.handle_event/3, at: lib/eshopy_web/live/cart_live/show.ex:55
[debug] Replied in 3ms
[error] GenServer #PID<0.1512.0> terminating
** (Ecto.StaleEntryError) attempted to delete a stale struct:

%Eshopy.ShoppingCart.Cart{__meta__: #Ecto.Schema.Metadata<:loaded, "carts">, id: 23, user_id: 1, user: #Ecto.Association.NotLoaded<association :user is not loaded>, cart_items: [%Eshopy.ShoppingCart.CartItem{__meta__: #Ecto.Schema.Metadata<:loaded, "cart_items">, id: 124, price: #Decimal<7500>, quantity: 3, cart_id: 23, cart: #Ecto.Association.NotLoaded<association :cart is not loaded>, product_id: 3, product: %Eshopy.Catalog.Product{__meta__: #Ecto.Schema.Metadata<:loaded, "products">, id: 3, description: "New Macbook", name: "MacBook", sku: 3, unit_price: #Decimal<2500>, image_upload: "/images/live_view_upload-1675197936-790406951694-1", available: true, brand_id: 2, brand: #Ecto.Association.NotLoaded<association :brand is not loaded>, category_id: 1, category: #Ecto.Association.NotLoaded<association :category is not loaded>, inserted_at: ~N[2023-01-31 20:45:38], updated_at: ~N[2023-02-04 18:47:25]}, inserted_at: ~N[2023-02-19 11:40:00], updated_at: ~N[2023-02-19 11:40:00]}, %Eshopy.ShoppingCart.CartItem{__meta__: #Ecto.Schema.Metadata<:loaded, "cart_items">, id: 122, price: #Decimal<1800>, quantity: 2, cart_id: 23, cart: #Ecto.Association.NotLoaded<association :cart is not loaded>, product_id: 5, product: %Eshopy.Catalog.Product{__meta__: #Ecto.Schema.Metadata<:loaded, "products">, id: 5, description: "New Phone", name: "Huawei P10 Lite", sku: 4, unit_price: #Decimal<900>, image_upload: "/images/live_view_upload-1675197961-897368113820-4", available: true, brand_id: 1, brand: #Ecto.Association.NotLoaded<association :brand is not loaded>, category_id: 3, category: #Ecto.Association.NotLoaded<association :category is not loaded>, inserted_at: ~N[2023-01-31 20:46:05], updated_at: ~N[2023-02-19 11:37:27]}, inserted_at: ~N[2023-02-19 11:39:53], updated_at: ~N[2023-02-19 11:39:53]}], inserted_at: ~N[2023-02-19 11:39:05], updated_at: ~N[2023-02-19 11:39:05]}

    (ecto 3.9.4) lib/ecto/repo/schema.ex:773: Ecto.Repo.Schema.apply/4
    (ecto 3.9.4) lib/ecto/repo/schema.ex:552: anonymous fn/11 in Ecto.Repo.Schema.do_delete/4
    (eshopy 0.1.0) lib/eshopy_web/live/cart_live/show.ex:55: EshopyWeb.CartLive.Show.handle_event/3
    (phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:396: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
    (telemetry 1.2.1) /home/mateusz/Pulpit/eshopy/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
    (phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:216: Phoenix.LiveView.Channel.handle_info/2
    (stdlib 4.2) gen_server.erl:1123: :gen_server.try_dispatch/4
    (stdlib 4.2) gen_server.erl:1200: :gen_server.handle_msg/6
    (stdlib 4.2) proc_lib.erl:250: :proc_lib.wake_up/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F0U27QcaUWhFkQXG", event: "event", payload: %{"event" => "clear_cart", "type" => "click", "value" => %{"value" => ""}}, ref: "10", join_ref: "4"}
State: %{components: {%{}, %{}, 1}, join_ref: "4", serializer: Phoenix.Socket.V2.JSONSerializer, socket: #Phoenix.LiveView.Socket<id: "phx-F0U27QcaUWhFkQXG", endpoint: EshopyWeb.Endpoint, view: EshopyWeb.CartLive.Show, parent_pid: nil, root_pid: #PID<0.1512.0>, router: EshopyWeb.Router, assigns: %{__changed__: %{}, cart: %Eshopy.ShoppingCart.Cart{__meta__: #Ecto.Schema.Metadata<:loaded, "carts">, id: 23, user_id: 1, user: #Ecto.Association.NotLoaded<association :user is not loaded>, cart_items: [%Eshopy.ShoppingCart.CartItem{__meta__: #Ecto.Schema.Metadata<:loaded, "cart_items">, id: 124, price: #Decimal<7500>, quantity: 3, cart_id: 23, cart: #Ecto.Association.NotLoaded<association :cart is not loaded>, product_id: 3, product: %Eshopy.Catalog.Product{__meta__: #Ecto.Schema.Metadata<:loaded, "products">, id: 3, description: "New Macbook", name: "MacBook", sku: 3, unit_price: #Decimal<2500>, image_upload: "/images/live_view_upload-1675197936-790406951694-1", available: true, brand_id: 2, brand: #Ecto.Association.NotLoaded<association :brand is not loaded>, category_id: 1, category: #Ecto.Association.NotLoaded<association :category is not loaded>, inserted_at: ~N[2023-01-31 20:45:38], updated_at: ~N[2023-02-04 18:47:25]}, inserted_at: ~N[2023-02-19 11:40:00], updated_at: ~N[2023-02-19 11:40:00]}, %Eshopy.ShoppingCart.CartItem{__meta__: #Ecto.Schema.Metadata<:loaded, "cart_items">, id: 122, price: #Decimal<1800>, quantity: 2, cart_id: 23, cart: #Ecto.Association.NotLoaded<association :cart is not loaded>, product_id: 5, product: %Eshopy.Catalog.Product{__meta__: #Ecto.Schema.Metadata<:loaded, "products">, id: 5, description: "New Phone", name: "Huawei P10 Lite", sku: 4, unit_price: #Decimal<900>, image_upload: "/images/live_view_upload-1675197961-897368113820-4", available: true, brand_id: 1, brand: #Ecto.Association.NotLoaded<association :brand is not loaded>, category_id: 3, category: #Ecto.Association.NotLoaded<association :category is not loaded>, inserted_at: ~N[2023-01-31 20:46:05], updated_at: ~N[2023-02-19 11:37:27]}, inserted_at: ~N[2023-02-19 11:39:53], updated_at: ~N[2023-02-19 11:39:53]}], inserted_at: ~N[2023-02-19 11:39:05], updated_at: ~N[2023-02-19 11:39:05]}, cart_items: [%Eshopy.ShoppingCart.CartItem{__meta__: #Ecto.Schema.Metadata<:loaded, "cart_items">, id: 124, price: #Decimal<7500>, quantity: 3, cart_id: 23, cart: #Ecto.Association.NotLoaded<association :cart is not loaded>, product_id: 3, product: %Eshopy.Catalog.Product{__meta__: #Ecto.Schema.Metadata<:loaded, "products">, id: 3, description: "New Macbook", name: "MacBook", sku: 3, unit_price: #Decimal<2500>, image_upload: "/images/live_view_upload-1675197936-790406951694-1", available: true, brand_id: 2, brand: #Ecto.Association.NotLoaded<association :brand is not loaded>, category_id: 1, category: #Ecto.Association.NotLoaded<association :category is not loaded>, inserted_at: ~N[2023-01-31 20:45:38], updated_at: ~N[2023-02-04 18:47:25]}, inserted_at: ~N[2023-02-19 11:40:00], updated_at: ~N[2023-02-19 11:40:00]}, %Eshopy.ShoppingCart.CartItem{__meta__: #Ecto.Schema.Metadata<:loaded, "cart_items">, id: 122, price: #Decimal<1800>, quantity: 2, cart_id: 23, cart: #Ecto.Association.NotLoaded<association :cart is not loaded>, product_id: 5, product: %Eshopy.Catalog.Product{__meta__: #Ecto.Schema.Metadata<:loaded, "products">, id: 5, description: "New Phone", name: "Huawei P10 Lite", sku: 4, unit_price: #Decimal<900>, image_upload: "/images/live_view_upload-1675197961-897368113820-4", available: true, brand_id: 1, brand: #Ecto.Association.NotLoaded<association :brand is not loaded>, category_id: 3, category: #Ecto.Association.NotLoaded<association :category is not loaded>, inserted_at: ~N[2023-01-31 20:46:05], updated_at: ~N[2023-02-19 11:37:27]}, inserted_at: ~N[2023-02-19 11:39:53], updated_at: ~N[2023-02-19 11:39:53]}], current_user: #Eshopy.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 1, email: "admin@pl", confirmed_at: nil, role: :user, customer: #Ecto.Association.NotLoaded<association :customer is not loaded>, inserted_at: ~N[2023-01-31 20:37:48], updated_at: ~N[2023-02-08 16:52:14], ...>, flash: %{"info" => "Product removed from cart"}, live_action: :show, product: [%Eshopy.Catalog.Product{__meta__: #Ecto.Schema.Metadata<:loaded, "products">, id: 12, description: "Computer mouse", name: "mouse", sku: 523452, unit_price: #Decimal<33>, image_upload: "/images/live_view_upload-1676759300-317036947925-1", available: true, brand_id: 3, brand: %Eshopy.Catalog.Brand{__meta__: #Ecto.Schema.Metadata<:loaded, "brands">, id: 3, name: "Logitech", image_upload: "/images/live_view_upload-1675197802-989508123695-6", products: #Ecto.Association.NotLoaded<association :products is not loaded>, inserted_at: ~N[2023-01-31 20:43:24], updated_at: ~N[2023-02-19 07:46:11]}, category_id: 1, category: %Eshopy.Catalog.Category{__meta__: #Ecto.Schema.Metadata<:loaded, "categories">, id: 1, name: "Notebook", image_upload: "/images/live_view_upload-1675197713-196034875224-5", products: #Ecto.Association.NotLoaded<association :products is not loaded>, ins (truncated)

I can see that one click sometimes invokes event two times. What provides to errors like this I think. First click deletes nicely everything, second tries to delete something already deleted.

The same happens when I click add product to cart from main window - it immediately creates two carts each of them has the same product, but It blocks whole app. I have restricted that user can only have one opened cart at the time, If cart exists, it leads to update cart already created, it cart doesnt exist it creates new one.

How to omit 10 times asking for confirmation pop-up? It makes me sick too and never happened before (when i used other front end tech). I’ve got loading JS script in root’s .

Thanks :slight_smile:

UPDATE 1: For now i solved double click problem. I dont really understand why it happens and if my solution is acceptable here but for some buttons i added phx-disable-with=“…” (like checkout button, or proceed), for buttons responsible for Delete, Change status or Add to cart I added phx-throttle=“1000”. Because sometimes previous attribute lead me to disable button until i refresh site.

UPDATE 2: As I can see the solution for all of problems I had to fight (except dozens asks for confirmation) was that Live View double clicks 99% of the time I click once. I think I can mark it as solution and topic can be closed :smiley:

1 Like

The “everything happens multiple times” behavior sounds like what I’d expect if some of the LiveView JS was being loaded into the page more than once - every declared event handler would wind up with multiple copies attached to the same browser events.

1 Like

This is what I read few times. Its JS oriented problem. The only thing is my JS is invoking user_socket from app.js, and 2-3 lines in root invoking app.js :smiley:

I need to dig more, maybe there is somewthing more about placement of and its influence on events like that :wink:

Thanks

Update: It was fast. I had duplicated line in root.html.heex

<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>