ResizeObserver - loop limit exceeded

Google ChromeAureliaMicrosoft EdgeRollbar

Google Chrome Problem Overview


About two months ago we started using Rollbar to notify us of various errors in our Web App. Ever since then we have been getting the occasional error:

ResizeObserver loop limit exceeded

The thing that confuses me about this is that we are not using ResizeObserver and I have investigated the only plugin which I thought could possibly be the culprit, namely:

Aurelia Resize

But it doesn't appear to be using ResizeObserver either.

What is also confusing is that these error messages have been occuring since January but ResizeObserver support has only recently been added to Chrome 65.

The browser versions that have been giving us this error are:

  • Chrome: 63.0.3239 (ResizeObserver loop limit exceeded)
  • Chrome: 64.0.3282 (ResizeObserver loop limit exceeded)
  • Edge: 14.14393 (SecurityError)
  • Edge: 15.15063 (SecurityError)

So I was wondering if this could possibly be a browser bug? Or perhaps an error that actually has nothing to do with ResizeObserver?

Google Chrome Solutions


Solution 1 - Google Chrome

You can safely ignore this error.

One of the specification authors wrote in a comment to your question but it is not an answer and it is not clear in the comment that the answer is really the most important one in this thread, and the one that made me comfortable to ignore it in our Sentry logs.

> This error means that ResizeObserver was not able to deliver all observations within a single animation frame. It is benign (your site will not break). – Aleksandar Totic Apr 15 at 3:14

There are also some related issues to this in the specification repository.

Solution 2 - Google Chrome

It's an old question but it still might be helpful to someone. You can avoid this error by wrapping the callback in requestAnimationFrame. For example:

const resizeObserver = new ResizeObserver(entries => {
   // We wrap it in requestAnimationFrame to avoid this error - ResizeObserver loop limit exceeded
   window.requestAnimationFrame(() => {
     if (!Array.isArray(entries) || !entries.length) {
       return;
     }
     // your code
   });
});

Solution 3 - Google Chrome

If you're using Cypress and this issue bumps in, you can safely ignore it in Cypress with the following code in support/index.js or commands.ts

const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on('uncaught:exception', (err) => {
    /* returning false here prevents Cypress from failing the test */
    if (resizeObserverLoopErrRe.test(err.message)) {
        return false
    }
})

You can follow the discussion about it here. As Cypress maintainer themselves proposed this solution, so I believe it'd be safe to do so.

Solution 4 - Google Chrome

We had this same issue. We found that a chrome extension was the culprit. Specifically, the loom chrome extension was causing the error (or some interaction of our code with loom extension). When we disabled the extension, our app worked.

I would recommend disabling certain extensions/addons to see if one of them might be contributing to the error.

Solution 5 - Google Chrome

For Mocha users:

The snippet below overrides the window.onerror hook mocha installs and turns the errors into a warning. https://github.com/mochajs/mocha/blob/667e9a21c10649185e92b319006cea5eb8d61f31/browser-entry.js#L74

// ignore ResizeObserver loop limit exceeded
// this is ok in several scenarios according to 
// https://github.com/WICG/resize-observer/issues/38
before(() => {
  // called before any tests are run
  const e = window.onerror;
  window.onerror = function(err) {
    if(err === 'ResizeObserver loop limit exceeded') {
      console.warn('Ignored: ResizeObserver loop limit exceeded');
      return false;
    } else {
      return e(...arguments);
    }
  }
});

not sure there is a better way..

Solution 6 - Google Chrome

add debounce like

new ResizeObserver(_.debounce(entries => {}, 200);

fixed this error for me

Solution 7 - Google Chrome

https://github1s.com/chromium/chromium/blob/master/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc#L44-L45 https://github1s.com/chromium/chromium/blob/master/third_party/blink/renderer/core/frame/local_frame_view.cc#L2211-L2212

After looking at the source code, it seems in my case the issue surfaced when the NotifyResizeObservers function was called, and there were no registered observers.

The GatherObservations function will return a min_depth of 4096, in case there are no observers, and in that case, we will get the "ResizeObserver loop limit exceeded" error.

The way I resolved it is to have an observer living throughout the lifecycle of the page.

Solution 8 - Google Chrome

In my case, the issue "ResizeObserver - loop limit exceeded" was triggered because of window.addEventListener("resize" and React's React.useState.

In details, I was working on the hook called useWindowResize where the use case was like this const [windowWidth, windowHeight] = useWindowResize();.

The code reacts on the windowWidth/windowHeight change via the useEffect.

React.useEffect(() => {
	ViewportService.dynamicDimensionControlledBy(
		"height",
		{ windowWidth, windowHeight },
		widgetModalRef.current,
		{ bottom: chartTitleHeight },
		false,
		({ h }) => setWidgetHeight(h),
	);
}, [windowWidth, windowHeight, widgetModalRef, chartTitleHeight]);

So any browser window resize caused that issue.

I've found that many similar issues caused because of the connection old-javascript-world (DOM manipulation, browser's events) and the new-javascript-world (React) may be solved by the setTimeout, but I would to avoid it and call it anti-pattern when possible.

So my fix is to wrap the setter method into the setTimeout function.

React.useEffect(() => {
	ViewportService.dynamicDimensionControlledBy(
		"height",
		{ windowWidth, windowHeight },
		widgetModalRef.current,
		{ bottom: chartTitleHeight },
		false,
		({ h }) => setTimeout(() => setWidgetHeight(h), 0),
	);
}, [windowWidth, windowHeight, widgetModalRef, chartTitleHeight]);

Solution 9 - Google Chrome

The error might be worth investigating. It can indicate a problem in your code that can be fixed.

In our case an observed resize of an element triggered a change on the page, which caused a resize of the first element again, which again triggered a change on the page, which again caused a resize of the first element, … You know how this ends.

Essentially we created an infinite loop that could not be fitted into a single animation frame, obviously. We broke it by holding up the change on the page using setTimeout() (although this is not perfect since it may cause some flickering to the users).

So every time ResizeObserver loop limit exceeded emerges in our Sentry now, we look at it as a useful hint and try to find the cause of the problem.

Solution 10 - Google Chrome

One line solution for Cypress. Edit the file support/commands.js with:

Cypress.on(
  'uncaught:exception',
  (err) => !err.message.includes('ResizeObserver loop limit exceeded')
);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIOIIOOIOView Question on Stackoverflow
Solution 1 - Google ChromeJacob RaskView Answer on Stackoverflow
Solution 2 - Google ChromeRaniView Answer on Stackoverflow
Solution 3 - Google ChromeKhateeb321View Answer on Stackoverflow
Solution 4 - Google ChromejrossView Answer on Stackoverflow
Solution 5 - Google ChromeJan KretschmerView Answer on Stackoverflow
Solution 6 - Google ChromeKrejaView Answer on Stackoverflow
Solution 7 - Google ChromeitayadView Answer on Stackoverflow
Solution 8 - Google ChromedominoView Answer on Stackoverflow
Solution 9 - Google ChromevasekchView Answer on Stackoverflow
Solution 10 - Google ChromeLikoView Answer on Stackoverflow