GoogleChrome/lighthouse · error

string collision: `message` and `description` are the same b

Error message

string collision: `message` and `description` are the same but differ in `placeholders`:\nkey: ${entry.key}\nmake `placeholders` match or update `message` or `description`s to explain why they don't match

What it means

Thrown by resolveMessageCollisions() when two or more UIStrings entries share the same `message` and `description` text but have differing `placeholders`. The deduplication logic can merge identical message+description pairs only if their placeholders also match; a mismatch would create translation ambiguity.

Source

Thrown at core/scripts/i18n/collect-strings.js:694

 *   should be changed to explain the need for different `placeholders`.
 *
 * Modifies `strings` in place to fix collisions.
 * @see https://github.com/GoogleChrome/lighthouse/blob/main/core/lib/i18n/README.md#collisions
 * @param {Record<string, CtcMessage>} strings
 */
function resolveMessageCollisions(strings) {
  const entries = Object.entries(strings).map(([key, ctc]) => ({key, ctc}));

  const stringsByMessage = arrayGroupToMap(entries, (entry) => entry.ctc.message);
  for (const messageGroup of stringsByMessage.values()) {
    // If this message didn't collide with anything else, skip it.
    if (messageGroup.length <= 1) continue;

    // For each group of matching message+description, placeholders must also match.
    const stringsByDescription = arrayGroupToMap(messageGroup, (entry) => entry.ctc.description);
    for (const descriptionGroup of stringsByDescription.values()) {
      if (!doPlaceholdersMatch(descriptionGroup)) {
        throw new Error('string collision: `message` and `description` are the same but differ in `placeholders`:\n' +
          descriptionGroup.map(entry => `key: ${entry.key}\n`).join('') +
          'make `placeholders` match or update `message` or `description`s to explain why they don\'t match');
      }
    }

    // If the entire message group has the same description and placeholders,
    // they can be translated as if a single message, no meaning needed.
    if (stringsByDescription.size <= 1) continue;

    // We have duplicate messages with different descriptions. Disambiguate using `meaning` for TC.
    for (const {ctc} of messageGroup) {
      ctc.meaning = ctc.description;
    }
  }
}

/**
 * Check that fixed collisions match our known list.

View on GitHub (pinned to 9515cd4e58)

Solutions

  1. Find the colliding keys listed in the error message and make their placeholders (example values) identical.
  2. If the placeholders are intentionally different, differentiate the `message` or `description` text to disambiguate.
  3. Consolidate the two keys into one shared message export.
Defensive patterns

Strategy: validation

Validate before calling

function findCollidingPlaceholders(strings) {
  const byMsg = new Map();
  for (const [key, ctc] of Object.entries(strings)) {
    const k = ctc.message + '||' + ctc.description;
    if (!byMsg.has(k)) byMsg.set(k, []);
    byMsg.get(k).push({key, placeholders: ctc.placeholders});
  }
  const collisions = [];
  for (const group of byMsg.values()) {
    if (group.length < 2) continue;
    const first = JSON.stringify(group[0].placeholders);
    if (group.some(g => JSON.stringify(g.placeholders) !== first)) collisions.push(group);
  }
  return collisions;
}

Prevention

When it happens

Trigger: Two different UIStrings keys in the codebase use the same English message and description but define different @example placeholder values, causing the generated placeholder metadata to differ.

Common situations: Duplicate messages across audit files where one was updated with new examples but the other wasn't; copy-pasted strings that diverged in placeholder definitions.

Related errors


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