{"record":{"id":"7642f185cbb31e7a","repo":"GoogleChrome/lighthouse","slug":"no-lcp-7642f1","errorCode":"NO_LCP","errorMessage":"The page did not display content that qualifies as a Largest Contentful Paint (LCP). Ensure the page has a valid LCP element and then try again. ({errorCode})","messagePattern":"The page did not display content that qualifies as a Largest Contentful Paint \\(LCP\\)\\. Ensure the page has a valid LCP element and then try again\\. \\((.+?)\\)","errorType":"exception","errorClass":"LighthouseError","httpStatus":null,"severity":"error","filePath":"core/computed/metrics/lcp-breakdown.js","lineNumber":29,"sourceCode":"import {TimeToFirstByte} from './time-to-first-byte.js';\nimport {LCPImageRecord} from '../lcp-image-record.js';\nimport {NavigationInsights} from '../navigation-insights.js';\n\n/**\n * Note: this omits renderDelay for simulated throttling.\n */\nclass LCPBreakdown {\n  /**\n   * @param {LH.Artifacts.MetricComputationDataInput} data\n   * @param {LH.Artifacts.ComputedContext} context\n   * @return {Promise<{ttfb: number, loadDelay?: number, loadDuration?: number, renderDelay?: number}>}\n   */\n  static async compute_(data, context) {\n    if (data.settings.throttlingMethod === 'simulate') {\n      const processedNavigation = await ProcessedNavigation.request(data.trace, context);\n      const observedLcp = processedNavigation.timings.largestContentfulPaint;\n      if (observedLcp === undefined) {\n        throw new LighthouseError(LighthouseError.errors.NO_LCP);\n      }\n      const timeOrigin = processedNavigation.timestamps.timeOrigin / 1000;\n\n      const {timing: ttfb} = await TimeToFirstByte.request(data, context);\n\n      const lcpRecord = await LCPImageRecord.request(data, context);\n      if (!lcpRecord) {\n        return {ttfb};\n      }\n\n      // Official LCP^tm. Will be lantern result if simulated, otherwise same as observedLcp.\n      const {timing: metricLcp} = await LargestContentfulPaint.request(data, context);\n      const throttleRatio = metricLcp / observedLcp;\n\n      const unclampedLoadStart = (lcpRecord.networkRequestTime - timeOrigin) * throttleRatio;\n      const loadDelay = Math.max(ttfb, Math.min(unclampedLoadStart, metricLcp));\n\n      const unclampedLoadEnd = (lcpRecord.networkEndTime - timeOrigin) * throttleRatio;","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/computed/metrics/lcp-breakdown.js#L11-L47","documentation":"Thrown as a LighthouseError with code NO_LCP from LCPBreakdown.compute_() at line 29. This code path handles the 'simulate' throttling method: it requests ProcessedNavigation and checks if the observed LCP timing exists. If largestContentfulPaint is undefined, it throws because LCP breakdown subparts (TTFB, load delay, load duration, render delay) cannot be decomposed without an LCP event.","triggerScenarios":"Calling LCPBreakdown.request() with settings.throttlingMethod === 'simulate' on a trace that has no LCP event. The simulation path still needs an observed LCP from the trace to decompose; without it, the throw at line 29 fires.","commonSituations":"Running LCP breakdown analysis on pages with no visible content. Pages rendered entirely by JavaScript that fails. Background/hidden tabs. This mirrors the same root cause as the standard NO_LCP error but is specifically in the LCP breakdown subpart computation.","solutions":["Ensure the page renders visible content to produce an LCP event","Switch to observed throttling (devtools/provided) if the simulation path is problematic, though the root cause is missing LCP","Verify the trace includes LCP-related categories if collecting manually","Handle this error gracefully if the page legitimately has no LCP (e.g., a 404 page)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check LCP for simulation path before requesting breakdown\nif (data.settings.throttlingMethod === 'simulate') {\n  const processedNavigation = await ProcessedNavigation.request(data.trace, context);\n  if (processedNavigation.timings.largestContentfulPaint === undefined) {\n    // No LCP — skip breakdown\n    return { ttfb: undefined };\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const breakdown = await LCPBreakdown.request(data, context);\n} catch (e) {\n  if (e instanceof LighthouseError && e.code === 'NO_LCP') {\n    // No LCP to break down — return partial or skip\n    return { notApplicable: true };\n  }\n  throw e;\n}","preventionTips":["Ensure the page produces an LCP event before requesting breakdown","Pre-check processedNavigation.timings.largestContentfulPaint in simulation mode","Handle NO_LCP gracefully in breakdown pipelines — it's a page condition, not a bug","Use recent Chrome with --headless=new for reliable paint capture"],"tags":["lcp","trace","performance","metrics","breakdown"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}