{"record":{"id":"635157ae02910ac7","repo":"angular/components","slug":"error-attempted-to-measure-an-item-that-isn-t-ren-635157","errorCode":null,"errorMessage":"Error: attempted to measure an item that isn't rendered.","messagePattern":"Error: attempted to measure an item that isn't rendered\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cdk/table/table.ts","lineNumber":1622,"sourceCode":"  }\n\n  /**\n   * Measures the size of the rendered range in the table.\n   * This is used for virtual scrolling when auto-sizing is enabled.\n   */\n  private _measureRangeSize(range: ListRange, orientation: 'horizontal' | 'vertical'): number {\n    if (range.start >= range.end || orientation !== 'vertical') {\n      return 0;\n    }\n\n    const renderedRange = this.viewChange.value;\n    const viewContainerRef = this._rowOutlet.viewContainer;\n\n    if (\n      (range.start < renderedRange.start || range.end > renderedRange.end) &&\n      (typeof ngDevMode === 'undefined' || ngDevMode)\n    ) {\n      throw Error(`Error: attempted to measure an item that isn't rendered.`);\n    }\n\n    const renderedStartIndex = range.start - renderedRange.start;\n    const rangeLen = range.end - range.start;\n    let firstNode: HTMLElement | undefined;\n    let lastNode: HTMLElement | undefined;\n\n    for (let i = 0; i < rangeLen; i++) {\n      const view = viewContainerRef.get(i + renderedStartIndex) as EmbeddedViewRef<unknown> | null;\n      if (view && view.rootNodes.length) {\n        firstNode = lastNode = view.rootNodes[0];\n        break;\n      }\n    }\n\n    for (let i = rangeLen - 1; i > -1; i--) {\n      const view = viewContainerRef.get(i + renderedStartIndex) as EmbeddedViewRef<unknown> | null;\n      if (view && view.rootNodes.length) {","sourceCodeStart":1604,"sourceCodeEnd":1640,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/table/table.ts#L1604-L1640","documentation":"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.","triggerScenarios":"_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.","commonSituations":"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.","solutions":["Ensure the requested range is within the viewport's renderedRange before measuring (clamp range to renderedRange)","Let the virtual scrolling module handle rendering: don't manually trigger measurement before renderedRange covers the items","Set proper itemSize and minBufferPx/maxBufferPx so ranges render ahead of measurement","Avoid programmatic scrollTo during init before the first render completes; wait for the viewport's rendered range event"],"exampleFix":"// before\nconst range = {start: 0, end: 100};\nmeasureRange(range); // may exceed renderedRange\n// after\nconst rendered = viewport.getRenderedRange();\nconst range = {start: Math.max(start, rendered.start), end: Math.min(end, rendered.end)};\nif (range.end > range.start) measureRange(range);","handlingStrategy":"validation","validationCode":"const rendered = viewport.getRenderedRange();\nif (range.start < rendered.start || range.end > rendered.end) {\n  range.start = Math.max(range.start, rendered.start);\n  range.end = Math.min(range.end, rendered.end);\n}","typeGuard":"function isWithinRenderedRange(range: {start: number; end: number}, rendered: {start: number; end: number}): boolean {\n  return range.start >= rendered.start && range.end <= rendered.end;\n}","tryCatchPattern":"try {\n  this.cdr.detectChanges();\n} catch (e) {\n  if (/attempted to measure an item that isn't rendered/.test(e.message)) {\n    console.error('Clamp the range to viewport.getRenderedRange() before measuring.');\n  }\n}","preventionTips":["Clamp ranges to getRenderedRange() before measuring","Configure itemSize and buffer sizes correctly","Avoid measuring before the virtual viewport's first render"],"tags":["angular","cdk-table","virtual-scroll","rendering"],"backgroundTag":"measuring-unrendered-item","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}