Debugging JavaScript Errors

ResizeObserver loop completed with undelivered notifications.

ResizeObserver loop completed with undelivered notifications.

The error, ResizeObserver loop completed with undelivered notifications. is a surprisingly common message that many TrackJS customers capture from their sites.

While concerning sounding, the error can often be ignored because the browser is just “working as designed”. Occasionally, the error is caused by a JavaScript bug causing excessive page re-rendering and should be fixed.

Our JavaScript Errors Index explores symptoms, causes, and solutions to common JavaScript errors.

Understanding the error

Unsurprisingly, this error occurs when JavaScript on the page is using the browser’s ResizeObserver API. The error is sent by the browser itself as an ErrorEvent and is received by any code listening for error events on window. That means you generally won’t see this in the developer console, but will see it in TrackJS and other error monitoring services.

Even if you don’t directly use ResizeObservers, many frameworks and libraries use it under the covers. For example, charting libraries often support responsive sizing/redrawing of charts by using ResizeObserver.

The message simply indicates that execution of a resize event callback was deferred until after the next frame render to avoid an infinite loop. In fact, it is specifically codified in the Resize Observer Specification. The “undelivered notifications” are not lost, but simply delayed one render cycle.

Since nothing is getting dropped on the floor, this error is more of a warning or informational message in most cases and is expected behavior for many uses of the ResizeObserver API.

Finding the root cause

JavaScript on your page is using the browser’s ResizeObserver API to invoke a callback when a DOM element’s size changes. The callback can modify the same element that originally triggered the resize event, triggering a second resize event. That new event is not sent to your callback until the next render cycle. The browser sends the ResizeObserver loop completed with undelivered notifications. error to inform you that this deferral has happened. ResizeObserver issues can cause Long Animation Frames, or LoAFs.

Deferring the event prevents infinite loops where the ResizeObserver callback receives a resize event, resizes the element in response, triggering a new resize event, which calls the callback, etc, etc.

It’s relatively simple to trigger this error ourselves:


<div id="watch-me" style="background-color: #red; height: 200px; width: 200px;"></div>
<script>
  // Create a ResizeObserver and give it our callback
  var observer = new ResizeObserver((entries) => {
    var entry = entries[0];
    console.log(`New size: ${entry.contentRect.width} x ${entry.contentRect.height}`);
    entry.target.style.width = "400px";
    // ^^^ Resize the div, triggering another resize event!
  });

  // Tell the observer which elements to watch
  var divToWatch = document.getElementById("watch-me");
  observer.observe(divToWatch);

  // Listen for error events bubbling out of the window object
  window.addEventListener("error", (e) => {
    console.error(e.message);
  });
</script>
Simple example of triggering the ResizeObserver error message
ResizeObserver error message, but size settles into stable state. This is not a bug.
ResizeObserver error message, but size settles into stable state. This is not a bug.

Can I ignore this error?

This error can be ignored as it is not user impacting in most cases. Further investigation is needed when the error repeats frequently or continuously in a single page load. This is an indication that the resize callback is constantly changing element sizes without settling into a final state. This is an extreme example:


<div id="watch-me" style="background-color: #red; height: 200px; width: 200px;"></div>
<script>
  // Create a ResizeObserver and give it our (buggy) callback
  var observer = new ResizeObserver((entries) => {
    var entry = entries[0];
    console.log(`New size: ${entry.contentRect.width} x ${entry.contentRect.height}`);
    entry.target.style.width = (entry.contentRect.width + 1) + "px";
    // ^^^ Resize the div every time. This is probably a bug!
  });

  // Tell the observer which elements to watch
  var divToWatch = document.getElementById("watch-me");
  observer.observe(divToWatch);

  // Listen for error events bubbling out of the window object
  window.addEventListener("error", (e) => {
    console.error(e.message);
  });
</script>
Buggy ResizeObserver callback causing continuous resizing and errors
Many ResizeObserver error messages, This is a bug.
Many ResizeObserver error messages, This is a bug.

How to fix

Rarely, this error message indicates a bug that needs to be fixed. The fix falls into two main cases:

1. A third party framework or library is using the ResizeObserver API

There is no one-size fits all solution in this case. Determine which specific dependency is causing the issue. Once the offending library has been found, ensure your code is using the library correctly. If things look good, it might be time to write a bug ticket!

2. Your own code is using the ResizeObserver API

It’s ok if your ResizeObserver callback modifies the size of elements. The important thing is ensure the callback “settles” into a stable state where element sizes are no longer being changed. Trace through your callback over several cycles and look for bugs in size calculations or other logic.

Monitor Your Environment!

Did your changes fix the issue? If you don’t monitor your production environment, how will you know? Errors come from lots of different places on the web. Some are noise, but many will cause user problems and block your users. TrackJS can tell you when errors happen, and more importantly, how to fix them.

Other JavaScript Errors

JavaScript Error rollup report in TrackJS

About TrackJS

The easiest way to track JavaScript errors. TrackJS monitors real errors from your website and reports all the context you need to recreate the problem and fix the bug. No complicated dashboards or custom queries, just the data you need to build better web applications.