GoogleChrome/lighthouse · error

${auditName} has no meta.id property, or the property is not

Error message

${auditName} has no meta.id property, or the property is not a string.

What it means

Thrown by assertValidAudit in validation.js. After confirming audit() exists, Lighthouse checks implementation.meta.id is a string (typeof === 'string'). meta.id is the audit's unique identifier referenced by categories/auditRefs. A missing meta, a non-string id (number, undefined), or a meta object without id fails the check.

Source

Thrown at core/config/validation.js:92

}

/**
 * Throws an error if the provided object does not implement the required properties of an audit
 * definition.
 * @param {LH.Config.AuditDefn} auditDefinition
 */
function assertValidAudit(auditDefinition) {
  const {implementation, path: auditPath} = auditDefinition;
  const auditName = auditPath ||
    implementation?.meta?.id ||
    'Unknown audit';

  if (typeof implementation.audit !== 'function' || implementation.audit === Audit.audit) {
    throw new Error(`${auditName} has no audit() method.`);
  }

  if (typeof implementation.meta.id !== 'string') {
    throw new Error(`${auditName} has no meta.id property, or the property is not a string.`);
  }

  if (!i18n.isStringOrIcuMessage(implementation.meta.title)) {
    throw new Error(`${auditName} has no meta.title property, or the property is not a string.`);
  }

  // If it'll have a ✔ or ✖ displayed alongside the result, it should have failureTitle
  const scoreDisplayMode = implementation.meta.scoreDisplayMode || Audit.SCORING_MODES.BINARY;
  if (
    !i18n.isStringOrIcuMessage(implementation.meta.failureTitle) &&
    scoreDisplayMode === Audit.SCORING_MODES.BINARY
  ) {
    throw new Error(`${auditName} has no meta.failureTitle and should.`);
  }

  if (!i18n.isStringOrIcuMessage(implementation.meta.description)) {
    throw new Error(
      `${auditName} has no meta.description property, or the property is not a string.`

View on GitHub (pinned to 9515cd4e58)

Solutions

  1. Set a string id in meta: static get meta() { return {id: 'my-audit', ...}; }.
  2. Use a unique, kebab-case id that matches what categories reference.
  3. Ensure meta is defined (not undefined) before meta.id is read.

Example fix

// before
class MyAudit extends Audit {
  static get meta() { return {id: 5, title:'X', description:'Y', requiredArtifacts:[]}; }
  static audit() {...}
}
// after
class MyAudit extends Audit {
  static get meta() { return {id: 'my-audit', title:'X', description:'Y', requiredArtifacts:[]}; }
  static audit() {...}
}
Defensive patterns

Strategy: validation

Validate before calling

function assertAuditMetaId(impl) {
  if (typeof impl.meta?.id !== 'string') {
    throw new TypeError(`Audit meta.id must be a string`);
  }
}

Type guard

function auditHasStringId(impl) {
  return typeof impl === 'function' && typeof impl.meta?.id === 'string';
}

Try / catch

try { new Config(config, {configPath}); }
catch (e) { if (/has no meta.id property/.test(e.message)) console.error('Add a string meta.id to the audit'); throw e; }

Prevention

When it happens

Trigger: An audit class returns meta without an id, or meta.id = 123 (number). typeof implementation.meta.id !== 'string' is true, so validation.js:92 throws (auditName defaults to path or 'Unknown audit').

Common situations: Forgetting id in the meta getter. Using a numeric id. meta defined as a plain object literal missing the id key. Copy-paste leaving id from a template.

Related errors


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