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
- Set a string id in meta: static get meta() { return {id: 'my-audit', ...}; }.
- Use a unique, kebab-case id that matches what categories reference.
- 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
- Always include id in the audit's meta (a unique kebab-case string).
- Ensure meta is defined before referencing meta.id.
- Verify meta.id matches the id used in category auditRefs.
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
- ${auditName} has no audit() method.
- ${pluginName} has an invalid category description.
- ${pluginName} has an invalid category manualDescription.
- ${pluginName} supportedModes must be an array, valid array v
- ${pluginName} groups json is not defined as an object.
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/fca82aa5716c861e.
Report an issue: GitHub.