Maximum call stack exceeded JS error

Hello Dash users!

Has anyone run into a “maximum call stack exceeded” JS error?

I’m unable to post a reproducible example, because it only comes up with my full site running.

I have narrowed it down: I have 4 callbacks with the same trigger. They update 3 plotly figures and one Div with some html content. If I removed any one of the 4 callbacks so that only 3 callbacks run, the callbacks run successfully. If all four run at once, I get the error. The same thing happens whether I write 4 callbacks with a single output or 1 callback with for outputs.

I think the way around this is to write a 3 output callback and a chained single output callback, but I’d like to understand what’s going on here. Is there a limit to how many objects can be updated simultaneously?

Thanks!

What’s in the call stack when it overflows? Is it Dash code, React code, plotly.js code?

In general you’ll probably see better performance with one multi-output callback instead of 3 with the same input (unless they’re all doing independent long calculations and you’re running multiple server processes), but it shouldn’t result in a stack error either way.

Thanks for replying Alex. I’m getting the following stack trace:

(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser's console.)
RangeError: Maximum call stack size exceeded

    at http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:315840

    at ut (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:312111)

    at Array.W.each (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:315814)

    at Object.plot [as plotMethod] (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:2648523)

    at SVGGElement.<anonymous> (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:2346930)

    at http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:315840

    at ut (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:312111)

    at Array.W.each (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:315814)

    at d (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:2346876)

    at Object.r.plot (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:2351122)

It’s sometimes but not always followed by another JS error:

TypeError: Cannot read property 'selectAll' of undefined

    at Object.r.clean (http://home.mikejarrett.ca:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:2351547)

    at Object.v.cleanPlot (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:2515564)

    at Object.r.purge (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/plotly-1.49.4.min.js?v=1.2.0&m=1568928449:7:2243293)

    at t.value (http://0.0.0.0:8051/_dash-component-suites/dash_core_components/dash_core_components.min.js?v=1.2.0&m=1568928449:47:228580)

    at callComponentWillUnmountWithTimer (http://0.0.0.0:8051/_dash-component-suites/dash_renderer/react-dom@16.8.6.js?v=1.1.0&m=1568928449:17304:12)

    at HTMLUnknownElement.callCallback (http://0.0.0.0:8051/_dash-component-suites/dash_renderer/react-dom@16.8.6.js?v=1.1.0&m=1568928449:143:14)

    at Object.invokeGuardedCallbackDev (http://0.0.0.0:8051/_dash-component-suites/dash_renderer/react-dom@16.8.6.js?v=1.1.0&m=1568928449:193:16)

    at invokeGuardedCallback (http://0.0.0.0:8051/_dash-component-suites/dash_renderer/react-dom@16.8.6.js?v=1.1.0&m=1568928449:250:31)

    at safelyCallComponentWillUnmount (http://0.0.0.0:8051/_dash-component-suites/dash_renderer/react-dom@16.8.6.js?v=1.1.0&m=1568928449:17311:5)

    at commitUnmount (http://0.0.0.0:8051/_dash-component-suites/dash_renderer/react-dom@16.8.6.js?v=1.1.0&m=1568928449:17688:11)

I’ve narrowed it down a bit more… the callbacks work fine when I simplify the layout. It’s some combination of the layout and the callbacks that’s causing the problem.

This looks like an infinite recursion in plotly.js. I know there have been some improvements in that regard recently, can you try updating to the latest dash version that contains plotly.js version 1.50.1? If it’s still happening on the latest version, we’ll probably need to know exactly what the figure prop is for the figure that’s breaking - or all of them, if we can’t figure out which figure it is.

Thanks Alex, I’ve updated to the latest Dash version but no change.

I’ve traced to problem back to a single change: Mixing dash bootstrap components (dbc.Col/dbc.Row) with plain html components ( html.Div(className=“row”) ) in a grid.

I still don’t understand what’s causing this – the page renders fine, and I only get the error when the callback runs. I’m just going to assume mixing dbc components with bootstrap-styled html components is a no-go. This is an easy change for me so I’ll probably leave it here.

1 Like

This error is almost always means you have a problem with recursion in JavaScript code, as there isn’t any other way in JavaScript to consume lots of stack. Sometimes calling a recursive function over and over again, causes the browser to send you Maximum call stack size exceeded error message as the memory that can be allocated for your use is not unlimited.

Be considerate while calling functions , also dry run is the best practice to prevent them. It’s possible to cause infinite recursion in a fully promisified code, too. That can happen if the promises in a chain don’t actually perform any asynchronous execution , in which case control never really returns to the event loop, even though the code otherwise appears to be asynchronous. That’s when it’s useful to wrap your recursive function call into a -

  • setTimeout
  • setImmediate or
  • process.nextTick

In some programming languages this can be solved with tail call optimization, where the recursion call is transformed under the hood into a loop so no maximum stack size reached error exists.

I just rand into the same recursion problem. In my case I was inserting a Dash DataTable into a layout with dbc.Row/dbc.Col. When I put the DataTable in a dbc.Row (with no dbc.Col) I get the recursion error.

Solution was to insert the table into a dbc.Col that was part of a dbc.Row, like this:

	dbc.Row(
		dbc.Col(
			#html.Label('Spike Errors'),
			myDashUtils.makeTable('spike-error-table', None, height=200)
		)
		), # row