binarypaladin

binarypaladin

"Catch-all" error handling in LiveView

In my total experience with LiveView, something that’s either a matter or personal ignorance or just problematic with how it works is generic error handling.

In the normal request/response cycle on a controller, catch-alls are pretty easy. We’ve got action_fallback to handle that and another controller out there dealing with errors.

I can’t see any way that this works nicely with LiveView in some sort of nice, transparent way. (Mind you, it’s quite possible someone provides an answer where I’m like, “D’oh!”)

To me, it’s looking like my main option would be to use on_mount for certain expected errors and then wrap other expected errors in helper functions that expect certain errors. That’s doable, but it seems like a repeat of assign_defaults in a different context.

There’s also one more issue:

While LiveView will try to recover by reseting state, most of the time the errors are not ephemeral. If the user does a thing that resulted in an error they’ll try again. We’re using Honeybadger for collecting these errors and I like presenting the user with, “Hey, provide this ID when contacting support.” A catch-all + flash or something seems like a workable solution here.

Is there something in the lifecycle I’m just missing and a sort of “blessed” way to do this? If not, what are some patterns that others have used for similar scenarios?

Most Liked

mayel

mayel

Just came across this old thread and wanted to notify you that I’ve since implemented it in a transparent way that doesn’t require repeating code in views or live components, by defining it in our Web module with @before_compile at bonfire_ui_common/lib/web.ex at main · bonfire-networks/bonfire_ui_common · GitHub and then bonfire_ui_common/lib/web.ex at main · bonfire-networks/bonfire_ui_common · GitHub

  defp live_mount_before_compile(env) do
    if Module.defines?(env.module, {:mount, 3}) do
      quote do
        defoverridable mount: 3

        def mount(params, session, socket) do
          undead_mount(socket, fn ->
            super(params, session, socket)
          end)
        end
      end
    end
  end
mayel

mayel

I’m sure it could be done transparently with macros but there’s something to be said for opt-in explicitness, but it’s not as much of a hassle as you expect, instead of wrapping all LiveView function bodies in undead, we do this:

  def handle_event(action, attrs, socket), do: Bonfire.UI.Common.LiveHandlers.handle_event(action, attrs, socket, __MODULE__, &do_handle_event/3)

and define do_handle_event/3 for view or component-specific logic, whilst LiveHandlers module takes care of error handling (and as a bonus also handles or delegates events that are used in more than one view or component).

binarypaladin

binarypaladin

This is excellent. Thank you for sharing this. Although you might be the person I blame if I’m up later than I’d planned, lol.

Where Next?

Popular in Questions Top

JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
hariharasudhan94
Lets say i have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => "XX...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42842 311
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35953 110
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement