GoogleChrome/lighthouse · error · Error

`getStandaloneReportHTML` is not set

Error message

`getStandaloneReportHTML` is not set

What it means

Thrown by ReportUIFeatures.getReportHtml when the renderer options (this._opts) do not include a getStandaloneReportHTML callback. That callback is the only way the report can reproduce its own HTML (used by the 'copy HTML' / save-as-html tools). The base ReportUIFeatures does not supply a default; the viewer subclass ViewerUIFeatures injects it via its constructor callbacks.

Source

Thrown at report/renderer/report-ui-features.js:167

    const buttonEl = this._dom.createChildOf(buttonsEl, 'button', classes.join(' '));
    buttonEl.textContent = opts.text;
    buttonEl.addEventListener('click', opts.onClick);
    return buttonEl;
  }

  resetUIState() {
    if (this._topbar) {
      this._topbar.resetUIState();
    }
  }

  /**
   * Returns the html that recreates this report.
   * @return {string}
   */
  getReportHtml() {
    if (!this._opts.getStandaloneReportHTML) {
      throw new Error('`getStandaloneReportHTML` is not set');
    }

    this.resetUIState();
    return this._opts.getStandaloneReportHTML();
  }

  /**
   * Save json as a gist. Unimplemented in base UI features.
   */
  saveAsGist() {
    // TODO ?
    throw new Error('Cannot save as gist from base report');
  }

  _enableFireworks() {
    const scoresContainer = this._dom.find('.lh-scores-container', this._dom.rootEl);
    scoresContainer.classList.add('lh-score100');
  }

View on GitHub (pinned to 9515cd4e58)

Solutions

  1. Pass a getStandaloneReportHTML function in the opts/callbacks: new ReportUIFeatures(dom, { getStandaloneReportHTML: () => generateStandaloneHtml }).
  2. Use ViewerUIFeatures instead of the base class — it requires and wires getStandaloneReportHTML for you.
  3. If you don't need HTML export, hide/disable the UI controls that call getReportHtml.

Example fix

// before
const features = new ReportUIFeatures(dom); // no opts

// after
const features = new ReportUIFeatures(dom, {
  getStandaloneReportHTML: () => ReportGenerator.generateReportHtml(lhr),
});
Defensive patterns

Strategy: validation

Validate before calling

const opts = {
  getStandaloneReportHTML: typeof getStandaloneReportHTML === 'function'
    ? getStandaloneReportHTML
    : () => ReportGenerator.generateReportHtml(currentLhr),
};
const features = new ReportUIFeatures(dom, opts);

Type guard

/** @param {LH.Renderer.Options} opts */
function hasStandaloneHtml(opts) {
  return typeof opts?.getStandaloneReportHTML === 'function';
}

Try / catch

try {
  features.getReportHtml();
} catch (err) {
  if (err.message === '`getStandaloneReportHTML` is not set') {
    // wire the callback and retry, or disable the HTML-export control
  } else throw err;
}

Prevention

When it happens

Trigger: Constructing new ReportUIFeatures(dom) (or with opts lacking getStandaloneReportHTML) and then invoking getReportHtml(), e.g. through a tools-menu action that calls it. Using the base class directly instead of ViewerUIFeatures.

Common situations: Embedding the Lighthouse report renderer in a custom host that instantiates ReportUIFeatures but forgets to wire the standalone-HTML generator. Copying example code that assumed viewer-only features.


AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13). Data as JSON: /api/errors/7422cd3ee63e8244. Report an issue: GitHub.