Skip to content

ResizeObserver loop limit exceeded

A ResizeObserver callback changed the size of an observed element in the same frame. The browser put off the extra notifications to the next frame and reported this error. The page usually keeps working.

Updated September 24, 2026 by the Squasher team

What the error means

ResizeObserver reports size changes before the browser paints. If a callback changes the size of an observed element, the browser checks again in the same frame, but only for elements deeper in the tree. Changes it cannot deliver move to the next frame, and the browser reports this error.

The error is sent to window.onerror, not thrown from your code, so it has no useful stack. The console may not show it, but window.onerror and error monitors do. Chrome used the old text ResizeObserver loop limit exceeded; current browsers use the text from the specification.

The error message in each browser or library
WhereMessage
Current Chrome, Edge, Firefox, SafariResizeObserver loop completed with undelivered notifications.
Older Chrome and EdgeResizeObserver loop limit exceeded

Common causes

  • The callback sets the width, height, padding, or font size of the element it observes.
  • The callback changes content or classes, and that changes the size of the observed element.
  • A library (charts, virtual lists, auto-growing text areas) measures and resizes in the same callback.
  • Two observed elements change each other's size, so each callback starts the other.

Reproduce it

Change the observed element's size inside its own callback. Listen on window to see the error, because the console may not show it.

TypeScript
window.addEventListener("error", (event) => console.log(event.message)); const box = document.querySelector<HTMLElement>("#box")!;new ResizeObserver(([entry]) => {  box.style.width = `${entry.contentRect.width + 1}px`; // resizes itself}).observe(box);// ResizeObserver loop completed with undelivered notifications.

Fix it

  1. Write in the next frame, and only on a real change

    Move the layout change into requestAnimationFrame, and skip it when the size did not change. Without the check, the resize runs again every frame.

    TypeScript
    let lastWidth = 0; const observer = new ResizeObserver(([entry]) => {  const width = Math.round(entry.contentRect.width);  if (width === lastWidth) return;  lastWidth = width;  requestAnimationFrame(() => chart.resize(width));});observer.observe(container);
  2. Observe the container, resize the child

    Watch an element whose size does not depend on what you change, such as a wrapper with a fixed or flexible width, and write to its child.

    TypeScript
    new ResizeObserver(([entry]) => {  canvas.width = Math.round(entry.contentRect.width); // child only}).observe(wrapper); // the wrapper's size does not follow the canvas
  3. Drop the known-benign message in your error monitor

    When the layout is correct and the message comes from a library you do not control, filter it before it is sent. Keep your own layout code free of the loop.

    TypeScript
    init({  apiKey: import.meta.env.VITE_SQUASHER_API_KEY,  projectId: import.meta.env.VITE_SQUASHER_PROJECT_ID,  beforeSend: (event) =>    event.message?.startsWith("ResizeObserver loop") ? null : event,});

Catch it in production

The Squasher browser SDK sends this error to your project when it happens, so you do not wait for a user to report it.

  • The browser SDK listens to the window error event, so this message is captured like any uncaught error.
  • beforeSend runs before every error event leaves the page. Return null to drop an event, or return a changed event.
  • The release on each event shows if a new component version started the loop.
src/monitoring.ts
import { init } from "@squasher-ai/browser"; init({  apiKey: import.meta.env.VITE_SQUASHER_API_KEY,  projectId: import.meta.env.VITE_SQUASHER_PROJECT_ID,  release: import.meta.env.VITE_GIT_SHA,  beforeSend: (event) =>    event.message?.startsWith("ResizeObserver loop") ? null : event,});
app.squasher.ai/acme/dashboard-web/issues

Error: ResizeObserver loop completed with undelivered notifications.

Error

LowUnresolvedError
Events
4,810
First seen
9d ago
Last seen
now
Environment
production
Service
dashboard-web

Example code and issue.

JavaScript error monitoring with Squasher

Catch the next one first.

Send browser errors to Squasher and fix them before the support ticket arrives.

Free plan. No credit card required.