✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Informing user of callback exceptions

What are some good options for showing some kind of error message to the user when a callback fails (throws an exception)? Right now there is the traceback in the console, but looking at the webpage, all that the user sees is that nothing happened.

I saw this thread: Improving handling of aborted callbacks but I don’t believe it addresses this aspect (please correct me if I’m wrong).

I’ve thought through some ways that this could be handled explicitly through Dash (a div with error messages that is the output of the potentially failing callback) but it seems very messy (especially if multiple callbacks involved) and involves duplicating information. Does react itself have some useful framework that could be used here?

2 Likes

Yep, the thread you linked to is just about improving the user experience for the developer, not the user of the app. I’m actually not sure that there is an easy way to achieve this at the moment, although @chriddyp might have some ideas.

From my understanding, callbacks wire up successful responses only to where they were originally being targeted. So there’s no current way to route a callback’s output to a different element midway through handling the callback. And routing it to a different element is going to be necessary for error messages since the target property isn’t always a suitable destination for an error message, or as you mention, might be an input of a chained callback.

I’ll second that this would be useful, to have a way to inform user of errors during execution of callback.

Another frustration of mine is when a Javascript error happens, the UI just stops being responsive with no feedback to user. As a developer i can know this happened by looking at chrome->developer tools. but user will have no idea what to do --> when the solution is that user should be informed of error and told to reload the page.

I’m wondering about this as well … I have some callbacks that will fail in some cases, and I’d like to display a warning to the user when they do.

I can imagine a few hack-ish ways of doing this, storing state in hidden divs, some try/excepts, etc., but this seems a bit clunky for production.

What I’d really like something like the solution proposed in Improving handling of aborted callbacks but with an addition like:

@app.handle_callback_errors(Output('my-user-warning-div', 'value'), [my_callback_func])
def handle_error(error):
    # whenever a callback (e.g. my_callback_func) raises a PreventUpdate exception, the exception
    # is passed to this handle_error function, which is itself a callback and can display a warning to the user

Would something like this be possible within the design of Dash?

Or even something like an Error class in addition to State, Input, Output, to explicitly handle errors when attempting to update a specified component. And then you could write a callback ‘as normal’ but with the appropriate Error as an input instead.

e.g. something like

@app.callback(Output('my-user-warning-div', 'value'), [Error('component-I-wanted-to-update', 'value-I-wanted-to-update')]:
def handle_error(error):
    # error is passed from the callback that failed when trying to update `component-I-wanted-to-update`

One pattern is to update the children property of a parent div instead of the attribute of your actual component. Then, your callback looks like:

@app.callback(Output('container', 'children'), [...])
def update_output(...)
    try:
         # ...
         return dcc.Graph(...) # or any other component
    except:
          return html.Div('An error occurred') # full control over the error UI

4 Likes

Thanks – that would definitely work, and is an improvement on how I’m currently doing things.

There are still two issues with that approach however:

  • If you want to keep the existing dcc.Graph, i.e. the update fails, but the existing graph should still be displayed, whereas if you overwrite this container div with an error message it is not (I’m sure there’s a way to work around this though)

  • Ideally, if the error is triggered by a control, I’d like to display an error specifically alongside that control – imagine an app where you have a single master graph, but a dozen separate controls that can do things to that graph, some of which (might) fail

Neither of these are show-stoppers, I’m just wondering if there’s a better way to do this.

@mkhorton

The first one is easy enough – just pass the current graph as a State variable.

The second one I would also like to do but seems extremely messy in the current framework. I guess you could modify the position of the output div, but you’d still not be sure of which control was triggered.

i switched to creating all my callbacks programmatically, so i handle all errors in the function that creates the callback

this is useful mostly for logging the errors (i found that exceptions in callbacks fail silently otherwise ,due to that suppress exceptions flags in a multi page app)

if there is a way of firing an event from within a callback and by that updating another output component (not the one used in the callback definition, that would solve the issue of displaying the error to the end user

Hi @chubukov, how you update a graph passed as a State? I’m only familiar with updating the figure with the return statement…

Thank you

@ pepe.bari - You still update the figure via the return statement. Including the graph as State simply makes the (current) state, i.e. how the graph looked before the callback invoked, available in the callback context. Using this state as the return value, the graph will stay unchanged.

Hi,

Please elaborate. Is ‘container’ the id of an html.Div in the layout? But I thought that returning a dcc.Graph requires the other variable to be 'figure’ and not 'children'. I’m pretty sure I tried returning a dcc.Graph to an html.Div as 'children' and it did not render properly.
I’ve also noticed that I get many more error messages in JupyterDash where as in my Flask app with embedded Dash apps, they only failed silently.