GoogleChrome/lighthouse · error · Error

onlyCategories cannot be an empty array.

Error message

onlyCategories cannot be an empty array.

What it means

Thrown by filterConfigByExplicitFilters in filters.js. Like onlyAudits, settings.onlyCategories may be null/undefined but must not be an empty array. An empty onlyCategories would request no categories, which Lighthouse treats as a misconfiguration and rejects immediately.

Source

Thrown at core/config/filters.js:269

    categories,
  };
}

/**
 * Filters a config's artifacts, audits, and categories down to the requested set.
 * Skip audits overrides inclusion via `onlyAudits`/`onlyCategories`.
 *
 * @param {LH.Config.ResolvedConfig} resolvedConfig
 * @param {Pick<LH.Config.Settings, 'onlyAudits'|'onlyCategories'|'skipAudits'>} filters
 * @return {LH.Config.ResolvedConfig}
 */
function filterConfigByExplicitFilters(resolvedConfig, filters) {
  const {onlyAudits, onlyCategories, skipAudits} = filters;
  if (onlyAudits && !onlyAudits.length) {
    throw new Error(`onlyAudits cannot be an empty array.`);
  }
  if (onlyCategories && !onlyCategories.length) {
    throw new Error(`onlyCategories cannot be an empty array.`);
  }

  errorOnUnknownOnlyCategories(resolvedConfig.categories, onlyCategories);

  let baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, undefined);
  if (onlyCategories) {
    baseAuditIds = getAuditIdsInCategories(resolvedConfig.categories, onlyCategories);
  } else if (onlyAudits) {
    baseAuditIds = new Set();
  } else if (!resolvedConfig.categories || !Object.keys(resolvedConfig.categories).length) {
    baseAuditIds = new Set(resolvedConfig.audits?.map(audit => audit.implementation.meta.id));
  }

  const auditIdsToKeep = new Set(
    [
      ...baseAuditIds, // Start with our base audits.
      ...(onlyAudits || []), // Additionally include the opt-in audits from `onlyAudits`.
      ...filterResistantAuditIds, // Always include any filter-resistant audits.

View on GitHub (pinned to 9515cd4e58)

Solutions

  1. Use undefined/null to mean 'all categories': const onlyCategories = list.length ? list : undefined.
  2. Require the user to pick at least one category before running.

Example fix

// before
const flags = {onlyCategories: picked}; // picked === []
// after
const flags = {onlyCategories: picked.length ? picked : undefined};
Defensive patterns

Strategy: validation

Validate before calling

if (Array.isArray(flags.onlyCategories) && flags.onlyCategories.length === 0) {
  flags.onlyCategories = undefined;
}

Type guard

function onlyCategoriesIsValid(v) { return v == null || (Array.isArray(v) && v.length > 0); }

Try / catch

try { await lighthouse(url, flags); }
catch (e) { if (/onlyCategories cannot be an empty array/.test(e.message)) { flags.onlyCategories = undefined; } throw e; }

Prevention

When it happens

Trigger: flags.onlyCategories = [] (e.g. from an empty selection). onlyCategories && !onlyCategories.length is true, so filters.js:269 throws.

Common situations: UI-driven category selection with nothing chosen. Programmatic default of [] instead of undefined. Spreading an empty list.

Related errors


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