Athunnea

Athunnea

What happens: User opens LiveView page and clicks a button. LiveView handle_event calls a function that crashes. LiveView restarts. User is unaware that something went wrong

What I expect to happen: user is informed that something went wrong. Classic controllers show the 500 error page in similar case.

Error and exception handling doc says

If the error happens during an event, the LiveView process will crash. The client will notice the error and remount the LiveView - without reloading the page. This is enough to update the page and show the user the latest information.

But nothing on how to track this and notify user. I guess I could wrap each function call in try/rescue block and issue a notification myself, but I hope there is a better way

I’d appreciate an advice

Showing Posts 1 to 10

APB9785

APB9785

Creator of ECSx

Inside handle_event you need to also handle the “bad” result(s) from your function call, usually with a case statement. For example:

def handle_event("some_event", params, socket) do
  case function_with_multiple_results(params) do
    good_result ->
      socket = intended_effects(socket)
      {:noreply, socket}

    bad_result ->
      socket = show_my_error_page(socket)
      {:noreply, socket}
  end
end
cenotaph

cenotaph

Display the error message on the view itself rather than sending them to a new page?

<% if @error do %>
<div class="error">You don't have permissions<div>
</div>
def handle_event("some_event", params, socket) do
  case function_with_multiple_results(params) do
    good_result ->
      socket = intended_effects(socket)
      {:noreply, socket}

    bad_result ->
      socket = assign(socket, error: "my error")
      {:noreply, socket}
  end
end

or

socket |> put_flash(socket, :info, "It worked!")
socket |> put_flash(socket, :error, "You can't access that page")
Athunnea

Athunnea OP

There might be a case when intended_effects() unexpectedly raises – due to a bug for example. In this case LV will just go back to mount. And a user has no idea that something went wrong, other than no changes on the page.

I’d expect LV to know about that. At least it knows if raise happens in mount() and shows the error page.

APB9785

APB9785

Creator of ECSx

In this scenario, the LiveView “goes back to mount” because it crashed and was replaced by a new LiveView, which knows nothing about the old one.

If you’re going to go through the effort of reporting the crash, you might as well just fix the error to not crash the LiveView! Within intended_effects() just like in handle_event you should have all possible cases accounted for (this is the standard in a functional language). If there is an error case, a changeset should be returned containing the errors and these errors displayed in the LV. It should never result in a LV crash.

Are you using Ecto to handle your data? Generally the Ecto callbacks return {:ok, struct} on success, and {:error, changeset} on failure. Then you can wrap them in a case statement like shown earlier:

case Accounts.update_user_password(user, password, user_params) do
  {:ok, _user} ->
    socket = put_flash(socket, :info, "Password updated successfully.")
    {:noreply, socket}

  {:error, changeset} ->
    socket = assign(socket, password_changeset: changeset)
    {:noreply, socket}
end

and display the errors to the user (here the example is for a password reset form)

<%= f = form_for @password_changeset, "#", phx_submit: "change_password" %>

  <%= if @password_changeset.action do %>
    <div class="alert alert-danger">
      <p>Oops, something went wrong! Please check the errors below.</p>
    </div>
  <% end %>

  <%= label f, :password, "New password" %>
  <%= password_input f, :password %>
  <%= error_tag f, :password %>

  <%= label f, :current_password, "Current password" %>
  <%= password_input f, :current_password %>
  <%= error_tag f, :current_password %>

  <%= submit "Change password" %>
</form>
Athunnea

Athunnea OP

I understand that the best approach is to produce bugs free code and expect all possible outcomes from functions. But bugs happen. Things go wrong. Not all things are as simple as Repo.update. There is always a lag between error reported and error fixed during which users face the error.

Seeing 500 page is no good. But even worse is not seeing it when something went wrong because then user has no idea if a function worked or not.

What I don’t understand is that exceptions on mount are caught and converted to an exception page by Phoenix error views - pretty much like the way it works with controllers - quote from LV docs. But exceptions on handle_event are not converted to error view. So if exception happens on mount - the user knows that there is a server error. If exception happens after a button click - the user is unaware, because the page stays the same.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

This isn’t exactly accurate. In some sense, this is less about mount vs handle_event, and more about the static vs live interactions. Crashes in any of the functions called statically are part of the plug pipeline (mount, handle_params) result in plug handling the error and then you get a 500. Those same functions (and any other functions) when called during the live render crash the process, and then the front end tries to reconnect.

Athunnea

Athunnea OP

It’s about user experience with the LiveView. If raise happens on mount the error page is rendered. If raise happens on handle_event - the error page is not rendered, and user is unaware that something went wrong, LiveView silently restarts without refreshing the page.

I’m looking for a way to let the user know that there was an error. Ideally without having to wrap all calls into try/rescue. So far I was unable to find anything in the docs

derek-zhou

derek-zhou

Both 500 and restarts are bad. In liveview, restart is simpler to implement, and in “deadview” 500 is simpler to implement. So what you are seeing here as discrepancy is the library making the least amount of effort when the developer’s intention is unknown.

Athunnea

Athunnea OP

I agee

I’m not looking for discrepancies. I’m looking for an answer to the question: How to notify a user about exception in the LiveView handle_event? I still hope there is a solution better than wrapping function calls with try/catch.

derek-zhou

derek-zhou

It should be possible to make a safe_handle_event wrapper macro to do that. Someone better than me in meta-programming can step up to take the challenge?

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
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
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
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
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

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews