handsontable/handsontable · warning

The ResizeObserver callback was fired too many times in dire

Error message

The ResizeObserver callback was fired too many times in direct succession.
This may be due to an infinite loop caused by setting a dynamic height/width (for example, with the `dvh` units) to a Handsontable container's parent. 
The observer will be disconnected.

What it means

Walkontable installs a ResizeObserver on the grid container to react to size changes. If the callback fires ~300 times in direct succession, it concludes a resize feedback loop exists (resizing the container re-triggers layout changes that resize it again) and disconnects the observer to stop burning CPU, warning the developer that auto-resize is now disabled for this table.

Source

Thrown at handsontable/src/3rdparty/walkontable/src/overlay/resizeMonitor.ts:73

   */
  #containerDomResizeCountTimeout: ReturnType<typeof setTimeout> | null = null;

  /**
   * The instance of the ResizeObserver that observes the size of the Walkontable wrapper element.
   * In case of the size change detection the `onContainerElementResize` is fired.
   *
   * @type {ResizeObserver}
   */
  #resizeObserver = new ResizeObserver((entries) => {
    requestAnimationFrame(() => {
      if (!Array.isArray(entries) || !entries.length) {
        return;
      }

      this.#containerDomResizeCount += 1;

      if (this.#containerDomResizeCount === 300) {
        warn('The ResizeObserver callback was fired too many times in direct succession.' +
          '\nThis may be due to an infinite loop caused by setting a dynamic height/width (for example, ' +
          'with the `dvh` units) to a Handsontable container\'s parent. ' +
          '\nThe observer will be disconnected.');

        this.#resizeObserver.disconnect();
      }

      // This logic is required to prevent an endless loop of the ResizeObserver callback.
      // https://github.com/handsontable/dev-handsontable/issues/1898#issuecomment-2154794817
      if (this.#containerDomResizeCountTimeout !== null) {
        clearTimeout(this.#containerDomResizeCountTimeout);
      }

      this.#containerDomResizeCountTimeout = setTimeout(() => {
        this.#containerDomResizeCount = 0;
      }, 100);

      this.#deps.wtSettings.getSetting('onContainerElementResize');

View on GitHub (pinned to 2c365a3291)

Solutions

  1. Replace dvh/vh units on the container's parent with a fixed height or a stable unit (px, %, or a JS-measured height)
  2. Decouple the parent's size from the grid's rendered size (overflow hidden, fixed wrapper height)
  3. If the warning was a false positive, re-initialize the table — the observer stays disconnected for that instance
  4. Update to the latest patch release, as loop-detection thresholds have been tuned

Example fix

// before
.hot-wrapper { height: 100dvh; }

// after
.hot-wrapper { height: calc(100vh - 60px); } /* stable, no per-frame reflow loop */
Defensive patterns

Strategy: validation

Validate before calling

const cs = getComputedStyle(document.querySelector('.hot-wrapper'));
const unstable = /d(vh|vw)|vh|vw/.test(cs.height + cs.width);
if (unstable) console.warn('viewport-relative sizing may cause ResizeObserver loop');

Prevention

When it happens

Trigger: Setting a dynamic viewport-relative size (e.g. height: 100dvh, 100vh) on a parent of the Handsontable container that interacts with mobile browser UI show/hide, or any CSS that makes the container's size oscillate every frame after each grid re-render.

Common situations: Mobile Safari/Chrome with dvh/vh units where toolbars expand/collapse, CSS animations or transitions on the container size, flex/grid layouts where the grid's own content height feeds back into the parent's height.

Related errors


AI-assisted analysis of handsontable/handsontable@2c365a3291 (2026-09-01). Data as JSON: /api/errors/ecd18a3a3bbc1c73. Report an issue: GitHub.