Dash app with js clientside callback sometimes crashes


I have moved many of my callbacks to the client side and the only callback are two functions that initially load the data and keep it in a div component, plus a figure component that is updated based on the div and some other dash-daq components/buttons. The app works well but if the div is big (many data points) and the user clicks some buttons after one another while the figure is updating through the callback, I get the following error/crash in the chrome console:

Any ideas on what I can do to debug and find a fix for the issue?




console error:

react-dom@16.8.6.min.js?v=1.1.0&m=1570107432:117 TypeError: Cannot read property '_subplot' of undefined
    at plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7
    at plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7
    at l (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)
    at Object.r.throttle (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)
    at Object.r.hover (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)
    at Object.t._fullLayout._rehover (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)
    at v.rehover (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)
    at Object.l.syncOrAsync (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)
    at r.plot (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)
    at Object.l.syncOrAsync (plotly-1.49.4.min.js?v=1.2.0&m=1570107433:7)

Looks the same as https://github.com/plotly/plotly.js/issues/4157 - which is closed only because we couldn’t find a reproducible example. If you can help us boil it down to something we can debug that would be much appreciated!

That’d be super.
How can I help? Can access to the app and an example on how to reproduce it help?
It does not happen often but when it happens, The user doesn’t know that the app has crashed.

Here is a deployment of the app on azure cloud:

I have left the debugging tools on, which may be helpful.
The way to reproduce the error is to

  1. Let the page load
  2. Slide the slider full to the right (Perfekt)
  3. While the app is running to replot the data, make 1/2 zoom actions
  4. immediately after zoom, click on buttons (“Viele Plots” and “Spannung” ) to turn them off.

This is where the error happens:

Here’s my attempt at reproducing this bug. I didn’t notice any console errors.

@bb09 Am I doing something wrong?

1 Like

@etienne I see the failure, following those same instructions (thanks @bb09!)
Looks like it’s coming from here: https://github.com/plotly/plotly.js/blob/25fe1c929672461e0b915a737134f6a975edf8f8/src/components/fx/hover.js#L242


Seems like perhaps the requirements of the bug are:

  • create a plot with multiple subplots (in this example we start with gd._fullLayout._subplots.cartesian = ["xy", "x2y2", "x3y3", "x4y4", "x5y5", "x6y6", "x7y7"]
  • start a slow update that’s going to remove some subplots (in the above example “perfekt” makes it slow, and turning off “Viele Plots” and “Spannung” reduces us to ["xy", "x2y2"] - zooming is not necessary to generate the error)
  • hover over one of the subplots that’s going to be removed
  • while hovered there, the update without that subplot comes back
  • we try to “rehover” on the no-longer-present subplot :boom:
1 Like

Incidentally @bb09 is there a reason you’re using 7 separate x axes all linked by matches: 'x7' rather than just a single x axis? It looks like they all have the same attributes, so I think the effect would be identical, but should be easier to construct and possibly a bit faster to draw.

This problem will be fixed in plotly.js v1.50.1 set to be released next week.


Super! That was fast. Thanks! Looking forward to it.

@alexcjohnson Actually I have been trying to make my redrawing faster but without any success.

What I use is as follows. Is there a better way to do the redrawing faster? Since the number of subplots depends on what file is loaded, which controls are on, and how many signals do I have, I redraw the figure with make_subplots function. I’d appreciate any tips to have faster redraws.

fig = make_subplots(rows=max(n_rows,1), cols=1,shared_xaxes=True,vertical_spacing=vertical_spacing)
if av_sig['V']:
    for trace1 in traces_v:
        fig.add_trace(trace1, row=row, col=1)
    fig.update_yaxes(title_text=labels_dict['V'], row=row, col=1,showspikes=True,spikemode="across+marker")
if av_sig['A']:
    for trace1 in traces_a:
        fig.add_trace(trace1, row=row, col=1)
    fig.update_yaxes(title_text=labels_dict['A'], row=row, col=1,showspikes=True,spikemode="across+marker")
if av_sig['D']:
    for trace1 in traces_d:
        fig.add_trace(trace1, row=row, col=1)
    fig.update_yaxes(title_text=labels_dict['D'], ticktext=[], tickvals=[], row=row, col=1,showspikes=True,spikemode="across+marker")
if xaxis_range:
    for row in range(1,n_rows+1):
        fig.update_xaxes(range=xaxis_range, row=row, col=1)
    margin=dict(t=fig_margin_t, b=fig_margin_b),
    showlegend= True,)
fig.update_xaxes(row=max(n_rows,2), col=1,title_text=TIME_LABEL, showticklabels=True)

Ah OK, I’m actually not that familiar with make_subplots - I guess under the hood it uses matches so that if you did have config differences between the subplots you’d have that flexibility. It’s probably not a big deal performance-wise, and make_subplots is hiding the duplication from you, so in the end it’s pretty clean code from your standpoint.

1 Like