GoogleChrome/lighthouse · error
must use same format and formatType for a given name. Invali
Error message
must use same format and formatType for a given name. Invalid for: ${rawName} What it means
Thrown during CTC conversion when the same placeholder rawName is used more than once in a message but with a different `format` or `formatType` (e.g. `{timeInMs, number, milliseconds}` vs `{timeInMs, number, seconds}`). The pipeline requires that a given placeholder name always maps to the same custom format so the generated CUSTOM_ICU_N placeholder is unambiguous.
Source
Thrown at core/scripts/i18n/collect-strings.js:346
icu.message += preambleText;
if (!rawName || !format || !formatType) continue;
// Check that custom-formatted ICU not using non-supported format ex:
// * using a second arg anything other than "number"
// * using a third arg that is not millis, secs, bytes, %, or extended %
if (!format.match(/^number$/)) {
throw Error(`Unsupported custom-formatted ICU format var "${format}" in message "${icu.message}"`);
}
if (!formatType.match(/milliseconds|seconds|bytes|percent|extendedPercent/)) {
throw Error(`Unsupported custom-formatted ICU type var "${formatType}" in message "${icu.message}"`);
}
let index;
const previousRawName = rawNameCache.get(rawName);
if (previousRawName) {
const [prevFormat, prevFormatType, prevIndex] = previousRawName;
if (prevFormat !== format || prevFormatType !== formatType) {
throw new Error(`must use same format and formatType for a given name. Invalid for: ${rawName}`);
}
index = prevIndex;
} else {
index = idx++;
rawNameCache.set(rawName, [format, formatType, index]);
}
// Append ICU replacements if there are any.
const placeholderName = `CUSTOM_ICU_${index}`;
icu.message += `$${placeholderName}$`;
let example;
// Make some good examples.
switch (formatType) {
case 'seconds':
example = '2.4';
break;View on GitHub (pinned to 9515cd4e58)
Solutions
- Rename one of the conflicting placeholders so each name maps to exactly one format/formatType pair.
- Align both usages to the same format and formatType.
- Search the message string for the rawName and reconcile all occurrences.
Example fix
// before
message: '{timeInMs, number, milliseconds} ms ({timeInMs, number, seconds})'
// after
message: '{timeInMs, number, milliseconds} ms ({timeInSec, number, seconds})' Defensive patterns
Strategy: validation
Validate before calling
function checkPlaceholderFormatConsistency(message) {
const re = /\{(?<name>\w+),\s*number,\s*(?<format>\w+)\}/g;
const seen = new Map();
let m;
while ((m = re.exec(message))) {
if (seen.has(m.groups.name) && seen.get(m.groups.name) !== m.groups.format) {
return false;
}
seen.set(m.groups.name, m.groups.format);
}
return true;
} Prevention
- Use distinct placeholder names per format type (timeInMs vs timeInSec).
- Audit all ICU placeholders in a message for format consistency before committing.
- Document the allowed format types: milliseconds, seconds, bytes, percent, extendedPercent.
When it happens
Trigger: Using the same ICU placeholder name with two different custom format annotations within the same message or across messages that share a name in the same conversion pass.
Common situations: Copy-pasting a placeholder for a different unit (bytes vs milliseconds) and forgetting to rename; refactoring that changes a format type in one place but not another.
Related errors
- [${err.message}] Did not find the expected syntax in message
- Content cannot appear outside plural or select ICU messages.
- Ctc messages cannot contain double dollar: ${icu.message}
- string collision: `message` and `description` are the same b
- unsupported JSDoc comment: ${JSON.stringify(comment)}
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/405aed8d2397881f.
Report an issue: GitHub.