React: ResizeObserver loop completed with undelivered notifications

Shivan M.

The Problem

In React, you may get the following error related to ResizeObserver:

ResizeObserver loop limit exceeded

This may be confusing if you haven’t used ResizeObserver directly in your codebase.

In most cases, you can safely ignore this error if you are experiencing it locally and you’re not using ResizeObserver directly.

However, let’s look at some common workarounds and solutions both for React and using ResizeObserver directly.

The Solution

If you are using ResizeObserver directly and experiencing the error, you may need to verify whether your implementation follows the specification for the ResizeObserver interface.

Implementations should invoke resize events before the frame under observation is presented to the user. If a resize event occurs, style and layout are re-evaluated, which may trigger more resize events. To avoid infinite loops from cyclic resize dependencies, each iteration only processes elements deeper in the DOM. If a resize event doesn’t meet that condition, it is deferred and an error event is fired.

This happens to prevent the browser from becoming unresponsive, but it does not prevent the infinite loop.

If your code is such that the resizing loop is not infinite, ResizeObserver will eventually settle and your layout should be correct. In the case that the error is firing, you may see that your application layout changes incrementally rather than all at once, as resize events are being delayed across multiple frames.

In the following code sample, the ResizeObserver updates the width of the divElem in a loop over the entries (including the divElem itself). This causes an infinite loop, which causes the error message to repeat every frame:

const divElem = document.querySelector("body > div"); const resizeObserver = new ResizeObserver((entries) => { console.log(entries) for (const entry of entries) { entry.target.style.width = entry.contentBoxSize[0].inlineSize + 10 + "px"; } }); resizeObserver.observe(divElem);

There are a few ways to stop the error from appearing, depending on your tech stack.

Workaround 1: Incognito Mode

To verify whether the error is caused by a browser extension, open your application in an incognito browser window, where no (or fewer) browser extensions are loaded. If the error does not occur in the incognito window without extensions active, you can assume that it was caused by an extension modifying the layout of your application.

Workaround 2: React and Webpack

If you are using React and Webpack, you can disable the notification from Webpack by modifying the configuration options for the dev server in webpack.config.js:

module.exports = { //... devServer: { client: { overlay: { runtimeErrors: (error) => { if (error.message === 'ResizeObserver loop limit exceeded') { return false; } return true; }, }, }, }, };

Workaround 3: Cypress Tests

If you are experiencing this error when running end-to-end tests with Cypress, you can add the following code to your configuration to ignore the error:

const resizeObserverLoopErrRe = /^ResizeObserver loop limit exceeded/ Cypress.on('uncaught:exception', (err) => { if (resizeObserverLoopErrRe.test(err.message)) { return false } })

Workaround 4: Sentry Error Monitoring

If you’d like to ignore this error in your Sentry reporting, you can add the error to the ignoreErrors parameter in the Configuration Options:

Sentry.init({ ... ignoreErrors: ['ResizeObserver loop limit exceeded'] })

Understanding the ResizeObserver loop limit exceeded Error Message

In the browser, the ResizeObserver interface reports changes to the dimensions of a browser element’s content, border box, or the bounding box of an SVG element.

You might use ResizeObserver to change the font size of an element as a slider is moved (causing a <div> to change width), as illustrated in the following code taken from the official MDN documentation:

const h1Elem = document.querySelector("h1"); const pElem = document.querySelector("p"); const divElem = document.querySelector("body > div"); const slider = document.querySelector('input[type="range"]'); const checkbox = document.querySelector('input[type="checkbox"]'); divElem.style.width = "600px"; slider.addEventListener("input", () => { divElem.style.width = `${slider.value}px`; }); const resizeObserver = new ResizeObserver((entries) => { for (const entry of entries) { if (entry.contentBoxSize) { const contentBoxSize = entry.contentBoxSize[0]; h1Elem.style.fontSize = `${Math.max( 1.5, contentBoxSize.inlineSize / 200, )}rem`; pElem.style.fontSize = `${Math.max( 1, contentBoxSize.inlineSize / 600, )}rem`; } else { h1Elem.style.fontSize = `${Math.max( 1.5, entry.contentRect.width / 200, )}rem`; pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`; } } console.log("Size changed"); }); resizeObserver.observe(divElem); checkbox.addEventListener("change", () => { if (checkbox.checked) { resizeObserver.observe(divElem); } else { resizeObserver.unobserve(divElem); } });

In some instances, the ResizeObserver loop limit exceeded error message might be due to a browser extension modifying the layout of your page, or a library in your application that initiates element resizes outside of the scope of the ResizeObserver specification.

Additional Reading

Get Started With Sentry

Get actionable, code-level insights to resolve React performance bottlenecks and errors.

  1. Create a free Sentry account

  2. Create a React project and note your DSN

  3. Grab the Sentry React SDK

npm install @sentry/react
  1. Configure your DSN
import React from "react"; import ReactDOM from "react-dom"; import * as Sentry from "@sentry/react"; import App from "./App"; Sentry.init({ dsn: "https://<key>@sentry.io/<project>" }); ReactDOM.render(<App />, document.getElementById("root"));

Check our documentation for the latest instructions.

Loved by over 4 million developers and more than 90,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

Share on Twitter
Bookmark this page
Ask a questionJoin the discussion

Related Answers

A better experience for your users. An easier life for your developers.

    TwitterGitHubDribbbleLinkedinDiscord
© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.