angular/components · error

Error: attempted to measure an item that isn't rendered.

Error message

Error: attempted to measure an item that isn't rendered.

What it means

CdkVirtualForOf.measureRangeSize(range, options) can only measure items that are currently rendered inside the viewport. The method throws when the requested index range falls outside the viewport's currently rendered range, since unrendered views have no DOM to measure.

Source

Thrown at src/cdk/scrolling/virtual-for-of.ts:215

      this._onRenderedDataChange();
    });
    this._viewport.attach(this);
  }

  /**
   * Measures the combined size (width for horizontal orientation, height for vertical) of all items
   * in the specified range. Throws an error if the range includes items that are not currently
   * rendered.
   */
  measureRangeSize(range: ListRange, orientation: 'horizontal' | 'vertical'): number {
    if (range.start >= range.end) {
      return 0;
    }
    if (
      (range.start < this._renderedRange.start || range.end > this._renderedRange.end) &&
      (typeof ngDevMode === 'undefined' || ngDevMode)
    ) {
      throw Error(`Error: attempted to measure an item that isn't rendered.`);
    }

    // The index into the list of rendered views for the first item in the range.
    const renderedStartIndex = range.start - this._renderedRange.start;
    // The length of the range we're measuring.
    const rangeLen = range.end - range.start;

    // Loop over all the views, find the first and land node and compute the size by subtracting
    // the top of the first node from the bottom of the last one.
    let firstNode: HTMLElement | undefined;
    let lastNode: HTMLElement | undefined;

    // Find the first node by starting from the beginning and going forwards.
    for (let i = 0; i < rangeLen; i++) {
      const view = this._viewContainerRef.get(i + renderedStartIndex) as EmbeddedViewRef<
        CdkVirtualForOfContext<T>
      > | null;
      if (view && view.rootNodes.length) {

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Only call measureRangeSize for indexes within the currently rendered range (viewport.getRenderedRange())
  2. Clamp the requested range to the rendered range before measuring
  3. Use the uniform measureRangeSize option 'header/footer' semantics carefully: when measuring all items, ensure the whole list is rendered (e.g. temporarily render all or measure only visible items)
  4. Defer measurement until after rendering completes (afterNextRender / requestAnimationFrame) and re-check the rendered range

Example fix

// before
const range = { start: 0, end: this.data.length };
this.viewport.measureRangeSize(range);
// after
const rendered = this.viewport.getRenderedRange();
const range = {
  start: Math.max(0, rendered.start),
  end: Math.min(this.data.length, rendered.end),
};
if (range.end > range.start) {
  this.viewport.measureRangeSize(range);
}
Defensive patterns

Strategy: validation

Validate before calling

const rendered = viewport.getRenderedRange();
const clamped = {
  start: Math.max(range.start, rendered.start),
  end: Math.min(range.end, rendered.end),
};
if (clamped.end > clamped.start) {
  viewport.measureRangeSize(clamped, options);
}

Type guard

function isWithinRenderedRange(range: ListRange, viewport: CdkVirtualScrollViewport): boolean {
  const rendered = viewport.getRenderedRange();
  return range.start >= rendered.start && range.end <= rendered.end;
}

Try / catch

try {
  viewport.measureRangeSize(range, options);
} catch (e) {
  if (e instanceof Error && e.message.includes("isn't rendered")) {
    console.warn('Range not rendered; skipping measurement for', range);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling measureRangeSize with a range whose start is before the rendered range start or whose end exceeds the rendered range end; measuring an index while scrolled far from it; measuring immediately after data changes before the rendered range updates.

Common situations: Programmatic autoscroll/measurement features that assume all items are rendered; measuring during fast scrolling when views outside the range were recycled; calling measureRangeSize before the viewport has rendered the requested indexes (e.g. right after pushing data).

Related errors


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/87ca8118e4ddff44. Report an issue: GitHub.