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

With virtual scrolling, the table measures row heights by examining already-rendered embedded views. This error is thrown when a requested render range extends outside the currently rendered range of views, meaning code tried to measure items that were never rendered to the DOM.

Source

Thrown at src/cdk/table/table.ts:1622

  }

  /**
   * Measures the size of the rendered range in the table.
   * This is used for virtual scrolling when auto-sizing is enabled.
   */
  private _measureRangeSize(range: ListRange, orientation: 'horizontal' | 'vertical'): number {
    if (range.start >= range.end || orientation !== 'vertical') {
      return 0;
    }

    const renderedRange = this.viewChange.value;
    const viewContainerRef = this._rowOutlet.viewContainer;

    if (
      (range.start < renderedRange.start || range.end > renderedRange.end) &&
      (typeof ngDevMode === 'undefined' || ngDevMode)
    ) {
      throw Error(`Error: attempted to measure an item that isn't rendered.`);
    }

    const renderedStartIndex = range.start - renderedRange.start;
    const rangeLen = range.end - range.start;
    let firstNode: HTMLElement | undefined;
    let lastNode: HTMLElement | undefined;

    for (let i = 0; i < rangeLen; i++) {
      const view = viewContainerRef.get(i + renderedStartIndex) as EmbeddedViewRef<unknown> | null;
      if (view && view.rootNodes.length) {
        firstNode = lastNode = view.rootNodes[0];
        break;
      }
    }

    for (let i = rangeLen - 1; i > -1; i--) {
      const view = viewContainerRef.get(i + renderedStartIndex) as EmbeddedViewRef<unknown> | null;
      if (view && view.rootNodes.length) {

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Ensure the requested range is within the viewport's renderedRange before measuring (clamp range to renderedRange)
  2. Let the virtual scrolling module handle rendering: don't manually trigger measurement before renderedRange covers the items
  3. Set proper itemSize and minBufferPx/maxBufferPx so ranges render ahead of measurement
  4. Avoid programmatic scrollTo during init before the first render completes; wait for the viewport's rendered range event

Example fix

// before
const range = {start: 0, end: 100};
measureRange(range); // may exceed renderedRange
// after
const rendered = viewport.getRenderedRange();
const range = {start: Math.max(start, rendered.start), end: Math.min(end, rendered.end)};
if (range.end > range.start) measureRange(range);
Defensive patterns

Strategy: validation

Validate before calling

const rendered = viewport.getRenderedRange();
if (range.start < rendered.start || range.end > rendered.end) {
  range.start = Math.max(range.start, rendered.start);
  range.end = Math.min(range.end, rendered.end);
}

Type guard

function isWithinRenderedRange(range: {start: number; end: number}, rendered: {start: number; end: number}): boolean {
  return range.start >= rendered.start && range.end <= rendered.end;
}

Try / catch

try {
  this.cdr.detectChanges();
} catch (e) {
  if (/attempted to measure an item that isn't rendered/.test(e.message)) {
    console.error('Clamp the range to viewport.getRenderedRange() before measuring.');
  }
}

Prevention

When it happens

Trigger: _stickyCellMeasure / range handling: range.start < renderedRange.start || range.end > renderedRange.end — e.g. sticky logic or programmatic scroll asking to measure rows outside the CdkVirtualScrollViewport's rendered window.

Common situations: Custom code calling internal APIs or scroll/measure hooks before the viewport has rendered the needed rows; mismatched itemSize/buffer settings causing ranges to drift; combining sticky headers with virtual scroll where the range isn't yet rendered after fast programmatic scrolling.

Related errors


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